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 0x10000/imm32/64KB
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 b8/copy-to-eax _test-buffered-file/imm32
330 05/add-to-eax 4/imm32
331 50/push-eax
332
333 e8/call clear-stream/disp32
334
335 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
336
337
338 68/push _test-output-stream/imm32
339
340 e8/call clear-stream/disp32
341
342 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
343
344
345 68/push _test-error-stream/imm32
346
347 e8/call clear-stream/disp32
348
349 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
350
351
352
353 68/push "3"/imm32
354 68/push _test-stream/imm32
355
356 e8/call write/disp32
357
358 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32
359
360
361 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32
362 89/copy 3/mod/direct 0/rm32/eax . . . 4/r32/esp . .
363
364
365 68/push 0x10/imm32/nbytes-of-args-for-get-num
366 50/push-eax/ed
367
368 e8/call tailor-exit-descriptor/disp32
369
370 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32
371
372
373
374 68/push _test-buffered-file/imm32
375
376 e8/call get-char/disp32
377
378 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
379
380
381 50/push-eax/ed
382 68/push _test-error-stream/imm32
383 68/push _test-output-stream/imm32
384 68/push _test-buffered-file/imm32
385
386 e8/call get-num/disp32
387
388
389 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32
390
391
392 68/push "F - test-get-num-reads-single-digit"/imm32
393 68/push 0x33/imm32
394 b8/copy-to-eax _test-output-stream/imm32
395 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 0xc/disp8 .
396
397 e8/call check-ints-equal/disp32
398
399 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32
400
401 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32
402 5d/pop-to-ebp
403 c3/return
404
405 test-get-num-aborts-on-non-digit-in-Look:
406
407
408 55/push-ebp
409 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . .
410
411
412
413 68/push _test-stream/imm32
414
415 e8/call clear-stream/disp32
416
417 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
418
419
420 b8/copy-to-eax _test-buffered-file/imm32
421 05/add-to-eax 4/imm32
422 50/push-eax
423
424 e8/call clear-stream/disp32
425
426 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
427
428
429 68/push _test-output-stream/imm32
430
431 e8/call clear-stream/disp32
432
433 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
434
435
436 68/push _test-error-stream/imm32
437
438 e8/call clear-stream/disp32
439
440 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
441
442
443
444 68/push "3"/imm32
445 68/push _test-stream/imm32
446
447 e8/call write/disp32
448
449 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32
450
451
452 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32
453 89/copy 3/mod/direct 0/rm32/eax . . . 4/r32/esp . .
454
455
456 68/push 0x10/imm32/nbytes-of-args-for-get-num
457 50/push-eax/ed
458
459 e8/call tailor-exit-descriptor/disp32
460
461 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32
462
463
464
465 50/push-eax/ed
466 68/push _test-error-stream/imm32
467 68/push _test-output-stream/imm32
468 68/push _test-buffered-file/imm32
469
470 e8/call get-num/disp32
471
472
473 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32
474
475
476
477 68/push "F - test-get-num-aborts-on-non-digit-in-Look"/imm32
478 68/push 2/imm32
479
480 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 .
481
482 e8/call check-ints-equal/disp32
483
484 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32
485
486 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32
487 5d/pop-to-ebp
488 c3/return
489
490 test-get-num-reads-multiple-digits:
491
492
493 55/push-ebp
494 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . .
495
496
497
498 68/push _test-stream/imm32
499
500 e8/call clear-stream/disp32
501
502 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
503
504
505 b8/copy-to-eax _test-buffered-file/imm32
506 05/add-to-eax 4/imm32
507 50/push-eax
508
509 e8/call clear-stream/disp32
510
511 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
512
513
514 68/push _test-output-stream/imm32
515
516 e8/call clear-stream/disp32
517
518 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
519
520
521 68/push _test-error-stream/imm32
522
523 e8/call clear-stream/disp32
524
525 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
526
527
528
529 68/push "3456"/imm32
530 68/push _test-stream/imm32
531
532 e8/call write/disp32
533
534 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32
535
536
537 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32
538 89/copy 3/mod/direct 0/rm32/eax . . . 4/r32/esp . .
539
540
541 68/push 0x10/imm32/nbytes-of-args-for-get-num
542 50/push-eax/ed
543
544 e8/call tailor-exit-descriptor/disp32
545
546 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32
547
548
549
550 68/push _test-buffered-file/imm32
551
552 e8/call get-char/disp32
553
554 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
555
556
557 50/push-eax/ed
558 68/push _test-error-stream/imm32
559 68/push _test-output-stream/imm32
560 68/push _test-buffered-file/imm32
561
562 e8/call get-num/disp32
563
564
565 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32
566
567
568 68/push "F - test-get-num-reads-multiple-digits"/imm32
569 68/push 0x36353433/imm32
570 b8/copy-to-eax _test-output-stream/imm32
571 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 0xc/disp8 .
572
573 e8/call check-ints-equal/disp32
574
575 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32
576
577 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32
578 5d/pop-to-ebp
579 c3/return
580
581 test-get-num-reads-multiple-digits-followed-by-nondigit:
582
583
584 55/push-ebp
585 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . .
586
587
588
589 68/push _test-stream/imm32
590
591 e8/call clear-stream/disp32
592
593 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
594
595
596 b8/copy-to-eax _test-buffered-file/imm32
597 05/add-to-eax 4/imm32
598 50/push-eax
599
600 e8/call clear-stream/disp32
601
602 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
603
604
605 68/push _test-output-stream/imm32
606
607 e8/call clear-stream/disp32
608
609 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
610
611
612 68/push _test-error-stream/imm32
613
614 e8/call clear-stream/disp32
615
616 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
617
618
619
620 68/push "3456 x"/imm32
621 68/push _test-stream/imm32
622
623 e8/call write/disp32
624
625 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32
626
627
628 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32
629 89/copy 3/mod/direct 0/rm32/eax . . . 4/r32/esp . .
630
631
632 68/push 0x10/imm32/nbytes-of-args-for-get-num
633 50/push-eax/ed
634
635 e8/call tailor-exit-descriptor/disp32
636
637 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32
638
639
640
641 68/push _test-buffered-file/imm32
642
643 e8/call get-char/disp32
644
645 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
646
647
648 50/push-eax/ed
649 68/push _test-error-stream/imm32
650 68/push _test-output-stream/imm32
651 68/push _test-buffered-file/imm32
652
653 e8/call get-num/disp32
654
655
656 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32
657
658
659 68/push "F - test-get-num-reads-multiple-digits-followed-by-nondigit"/imm32
660 68/push 0x36353433/imm32
661 b8/copy-to-eax _test-output-stream/imm32
662 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 0xc/disp8 .
663
664 e8/call check-ints-equal/disp32
665
666 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32
667
668 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32
669 5d/pop-to-ebp
670 c3/return
671
672
673
674
675 expected:
676
677 55/push-ebp
678 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . .
679
680
681 68/push "Error: "/imm32
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 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 .
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 " expected\n"/imm32
698 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 .
699
700 e8/call write/disp32
701
702 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32
703
704
705 68/push 1/imm32
706 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 .
707
708 e8/call stop/disp32
709
710 $expected:dead-end:
711
712 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . .
713 5d/pop-to-ebp
714 c3/return
715
716
717 get-char:
718
719 55/push-ebp
720 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . .
721
722 50/push-eax
723
724
725 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 .
726
727 e8/call read-byte-buffered/disp32
728
729 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32
730
731 89/copy 0/mod/indirect 5/rm32/.disp32 . . 0/r32/eax Look/disp32 .
732 $get-char:end:
733
734 58/pop-to-eax
735
736 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . .
737 5d/pop-to-ebp
738 c3/return
739
740 is-digit?:
741
742 55/push-ebp
743 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . .
744
745 b8/copy-to-eax 0/imm32
746
747 81 7/subop/compare 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 0x30/imm32
748 7c/jump-if-lesser $is-digit?:end/disp8
749
750 81 7/subop/compare 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 0x39/imm32
751 7f/jump-if-greater $is-digit?:end/disp8
752
753 b8/copy-to-eax 1/imm32
754 $is-digit?:end:
755
756 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . .
757 5d/pop-to-ebp
758 c3/return
759
760 == data
761
762 Look:
763 0/imm32
764
765