https://github.com/akkartik/mu/blob/master/apps/crenshaw2-1b.subx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 == code
29
30
31
32
33 Entry:
34
35 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . .
36
37
38
39
40 68/push Heap/imm32
41 68/push Heap-size/imm32
42
43 e8/call new-segment/disp32
44
45 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32
46
47
48
49 81 7/subop/compare 1/mod/*+disp8 5/rm32/ebp . . . . 0/disp8 1/imm32
50 7e/jump-if-lesser-or-equal $run-main/disp8
51
52
53
54 68/push "test"/imm32
55 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 .
56
57 e8/call kernel-string-equal?/disp32
58
59 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32
60
61 3d/compare-eax-and 0/imm32
62 74/jump-if-equal $run-main/disp8
63
64 e8/call run-tests/disp32
65
66 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/ebx Num-test-failures/disp32
67 eb/jump $main:end/disp8
68 $run-main:
69
70
71 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32
72 89/copy 3/mod/direct 0/rm32/eax . . . 4/r32/esp . .
73
74
75 c7 0/subop/copy 0/mod/direct 0/rm32/eax . . . . . 0/imm32
76
77
78 50/push-eax/ed
79 68/push 2/imm32/stderr
80 68/push 1/imm32/stdout
81 68/push Stdin/imm32
82
83 e8/call compile/disp32
84
85 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32
86
87 bb/copy-to-ebx 0/imm32
88 $main:end:
89 b8/copy-to-eax 1/imm32/exit
90 cd/syscall 0x80/imm8
91
92
93 compile:
94
95 55/push-ebp
96 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . .
97
98 50/push-eax
99 51/push-ecx
100
101
102
103 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 .
104
105 e8/call get-char/disp32
106
107 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
108
109
110
111
112
113 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x13/imm32
114 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . .
115
116
117 c7 0/subop/copy 1/mod/*+disp8 1/rm32/ecx . . . . 8/disp8 7/imm32
118
119
120 51/push-ecx
121
122 e8/call clear-stream/disp32
123
124 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
125
126
127
128 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x14/disp8 .
129 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 .
130 51/push-ecx/num
131 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 .
132
133 e8/call get-num/disp32
134
135 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32
136
137
138
139
140
141
142
143 68/push "bb/copy-to-ebx "/imm32
144 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 .
145
146 e8/call write/disp32
147
148 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32
149
150
151 51/push-ecx/num
152 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 .
153
154 e8/call write-stream/disp32
155
156 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32
157
158
159 68/push Newline/imm32
160 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 .
161
162 e8/call write/disp32
163
164 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32
165
166
167 68/push "b8/copy-to-eax 1/imm32/exit\n"/imm32
168 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 .
169
170 e8/call write/disp32
171
172 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32
173
174
175 68/push "cd/syscall 0x80/imm8\n"/imm32
176 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 .
177
178 e8/call write/disp32
179
180 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32
181 $compile:end:
182
183 59/pop-to-ecx
184 58/pop-to-eax
185
186 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . .
187 5d/pop-to-ebp
188 c3/return
189
190
191
192
193
194 get-num:
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220 55/push-ebp
221 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . .
222
223
224
225 ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Look/disp32 .
226
227 e8/call is-digit?/disp32
228
229 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
230
231 3d/compare-eax-and 0/imm32
232 75/jump-if-not-equal $get-num:main/disp8
233
234
235 68/push "integer"/imm32
236 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 .
237 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x14/disp8 .
238
239 e8/call expected/disp32
240
241 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32
242 $get-num:main:
243
244
245 50/push-eax
246 51/push-ecx
247 52/push-edx
248 53/push-ebx
249 56/push-esi
250 57/push-edi
251
252
253 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 .
254
255 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 0xc/disp8 .
256
257 8b/copy 0/mod/indirect 7/rm32/edi . . . 1/r32/ecx . .
258
259 8b/copy 1/mod/*+disp8 7/rm32/edi . . . 2/r32/edx 8/disp8 .
260 $get-num:loop:
261
262 39/compare 3/mod/direct 2/rm32/edx . . . 1/r32/ecx . .
263 7d/jump-if-lesser $get-num:loop-stage2/disp8
264
265
266 68/push "get-num: too many digits in number"/imm32
267 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 .
268 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x14/disp8 .
269
270 e8/call error/disp32
271
272 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32
273 $get-num:loop-stage2:
274
275 8d/copy-address 1/mod/*+disp8 4/rm32/sib 7/base/edi 1/index/ecx . 3/r32/ebx 0xc/disp8 .
276 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 0/r32/eax Look/disp32 .
277 88/copy-byte 0/mod/indirect 3/rm32/ebx . . . 0/r32/AL . .
278
279 41/increment-ecx
280
281
282 56/push-esi
283
284 e8/call get-char/disp32
285
286 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
287
288
289
290 ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Look/disp32 .
291
292 e8/call is-digit?/disp32
293
294 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
295
296 3d/compare-eax-and 0/imm32
297 0f 85/jump-if-not-equal $get-num:loop/disp32
298 $get-num:loop-end:
299
300 89/copy 0/mod/indirect 7/rm32/edi . . . 1/r32/ecx . .
301 $get-num:end:
302
303 5f/pop-to-edi
304 5e/pop-to-esi
305 5b/pop-to-ebx
306 5a/pop-to-edx
307 59/pop-to-ecx
308 58/pop-to-eax
309
310 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . .
311 5d/pop-to-ebp
312 c3/return
313
314 test-get-num-reads-single-digit:
315
316
317 55/push-ebp
318 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . .
319
320
321
322 68/push _test-stream/imm32
323
324 e8/call clear-stream/disp32
325
326 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
327
328
329 68/push _test-buffered-file->buffer/imm32
330
331 e8/call clear-stream/disp32
332
333 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
334
335
336 68/push _test-output-stream/imm32
337
338 e8/call clear-stream/disp32
339
340 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
341
342
343 68/push _test-error-stream/imm32
344
345 e8/call clear-stream/disp32
346
347 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
348
349
350
351 68/push "3"/imm32
352 68/push _test-stream/imm32
353
354 e8/call write/disp32
355
356 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32
357
358
359 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32
360 89/copy 3/mod/direct 0/rm32/eax . . . 4/r32/esp . .
361
362
363 68/push 0x10/imm32/nbytes-of-args-for-get-num
364 50/push-eax/ed
365
366 e8/call tailor-exit-descriptor/disp32
367
368 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32
369
370
371
372 68/push _test-buffered-file/imm32
373
374 e8/call get-char/disp32
375
376 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
377
378
379 50/push-eax/ed
380 68/push _test-error-stream/imm32
381 68/push _test-output-stream/imm32
382 68/push _test-buffered-file/imm32
383
384 e8/call get-num/disp32
385
386
387 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32
388
389
390 68/push "F - test-get-num-reads-single-digit"/imm32
391 68/push 0x33/imm32
392 b8/copy-to-eax _test-output-stream/imm32
393 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 0xc/disp8 .
394
395 e8/call check-ints-equal/disp32
396
397 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32
398
399 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32
400 5d/pop-to-ebp
401 c3/return
402
403 test-get-num-aborts-on-non-digit-in-Look:
404
405
406 55/push-ebp
407 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . .
408
409
410
411 68/push _test-stream/imm32
412
413 e8/call clear-stream/disp32
414
415 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
416
417
418 68/push _test-buffered-file->buffer/imm32
419
420 e8/call clear-stream/disp32
421
422 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
423
424
425 68/push _test-output-stream/imm32
426
427 e8/call clear-stream/disp32
428
429 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
430
431
432 68/push _test-error-stream/imm32
433
434 e8/call clear-stream/disp32
435
436 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
437
438
439
440 68/push "3"/imm32
441 68/push _test-stream/imm32
442
443 e8/call write/disp32
444
445 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32
446
447
448 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32
449 89/copy 3/mod/direct 0/rm32/eax . . . 4/r32/esp . .
450
451
452 68/push 0x10/imm32/nbytes-of-args-for-get-num
453 50/push-eax/ed
454
455 e8/call tailor-exit-descriptor/disp32
456
457 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32
458
459
460
461 50/push-eax/ed
462 68/push _test-error-stream/imm32
463 68/push _test-output-stream/imm32
464 68/push _test-buffered-file/imm32
465
466 e8/call get-num/disp32
467
468
469 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32
470
471
472
473 68/push "F - test-get-num-aborts-on-non-digit-in-Look"/imm32
474 68/push 2/imm32
475
476 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 .
477
478 e8/call check-ints-equal/disp32
479
480 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32
481
482 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32
483 5d/pop-to-ebp
484 c3/return
485
486 test-get-num-reads-multiple-digits:
487
488
489 55/push-ebp
490 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . .
491
492
493
494 68/push _test-stream/imm32
495
496 e8/call clear-stream/disp32
497
498 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
499
500
501 68/push _test-buffered-file->buffer/imm32
502
503 e8/call clear-stream/disp32
504
505 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
506
507
508 68/push _test-output-stream/imm32
509
510 e8/call clear-stream/disp32
511
512 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
513
514
515 68/push _test-error-stream/imm32
516
517 e8/call clear-stream/disp32
518
519 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
520
521
522
523 68/push "3456"/imm32
524 68/push _test-stream/imm32
525
526 e8/call write/disp32
527
528 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32
529
530
531 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32
532 89/copy 3/mod/direct 0/rm32/eax . . . 4/r32/esp . .
533
534
535 68/push 0x10/imm32/nbytes-of-args-for-get-num
536 50/push-eax/ed
537
538 e8/call tailor-exit-descriptor/disp32
539
540 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32
541
542
543
544 68/push _test-buffered-file/imm32
545
546 e8/call get-char/disp32
547
548 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
549
550
551 50/push-eax/ed
552 68/push _test-error-stream/imm32
553 68/push _test-output-stream/imm32
554 68/push _test-buffered-file/imm32
555
556 e8/call get-num/disp32
557
558
559 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32
560
561
562 68/push "F - test-get-num-reads-multiple-digits"/imm32
563 68/push 0x36353433/imm32
564 b8/copy-to-eax _test-output-stream/imm32
565 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 0xc/disp8 .
566
567 e8/call check-ints-equal/disp32
568
569 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32
570
571 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32
572 5d/pop-to-ebp
573 c3/return
574
575 test-get-num-reads-multiple-digits-followed-by-nondigit:
576
577
578 55/push-ebp
579 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . .
580
581
582
583 68/push _test-stream/imm32
584
585 e8/call clear-stream/disp32
586
587 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
588
589
590 68/push _test-buffered-file->buffer/imm32
591
592 e8/call clear-stream/disp32
593
594 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
595
596
597 68/push _test-output-stream/imm32
598
599 e8/call clear-stream/disp32
600
601 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
602
603
604 68/push _test-error-stream/imm32
605
606 e8/call clear-stream/disp32
607
608 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
609
610
611
612 68/push "3456 x"/imm32
613 68/push _test-stream/imm32
614
615 e8/call write/disp32
616
617 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32
618
619
620 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32
621 89/copy 3/mod/direct 0/rm32/eax . . . 4/r32/esp . .
622
623
624 68/push 0x10/imm32/nbytes-of-args-for-get-num
625 50/push-eax/ed
626
627 e8/call tailor-exit-descriptor/disp32
628
629 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32
630
631
632
633 68/push _test-buffered-file/imm32
634
635 e8/call get-char/disp32
636
637 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
638
639
640 50/push-eax/ed
641 68/push _test-error-stream/imm32
642 68/push _test-output-stream/imm32
643 68/push _test-buffered-file/imm32
644
645 e8/call get-num/disp32
646
647
648 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32
649
650
651 68/push "F - test-get-num-reads-multiple-digits-followed-by-nondigit"/imm32
652 68/push 0x36353433/imm32
653 b8/copy-to-eax _test-output-stream/imm32
654 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 0xc/disp8 .
655
656 e8/call check-ints-equal/disp32
657
658 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32
659
660 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32
661 5d/pop-to-ebp
662 c3/return
663
664
665
666
667 expected:
668
669 55/push-ebp
670 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . .
671
672
673 68/push "Error: "/imm32
674 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 .
675
676 e8/call write/disp32
677
678 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32
679
680
681 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 .
682 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 .
683
684 e8/call write/disp32
685
686 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32
687
688
689 68/push " expected\n"/imm32
690 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 .
691
692 e8/call write/disp32
693
694 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32
695
696
697 68/push 1/imm32
698 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 .
699
700 e8/call stop/disp32
701
702 $expected:dead-end:
703
704 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . .
705 5d/pop-to-ebp
706 c3/return
707
708
709 get-char:
710
711 55/push-ebp
712 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . .
713
714 50/push-eax
715
716
717 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 .
718
719 e8/call read-byte-buffered/disp32
720
721 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
722
723 89/copy 0/mod/indirect 5/rm32/.disp32 . . 0/r32/eax Look/disp32 .
724 $get-char:end:
725
726 58/pop-to-eax
727
728 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . .
729 5d/pop-to-ebp
730 c3/return
731
732 is-digit?:
733
734 55/push-ebp
735 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . .
736
737 b8/copy-to-eax 0/imm32
738
739 81 7/subop/compare 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 0x30/imm32
740 7c/jump-if-lesser $is-digit?:end/disp8
741
742 81 7/subop/compare 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 0x39/imm32
743 7f/jump-if-greater $is-digit?:end/disp8
744
745 b8/copy-to-eax 1/imm32
746 $is-digit?:end:
747
748 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . .
749 5d/pop-to-ebp
750 c3/return
751
752 == data
753
754 Look:
755 0/imm32
756
757