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