https://github.com/akkartik/mu/blob/master/apps/braces.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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 == code
52
53 Entry:
54
55 89/<- %ebp 4/r32/esp
56
57 (new-segment Heap-size Heap)
58
59 81 7/subop/compare *ebp 1/imm32
60 7e/jump-if-lesser-or-equal $subx-braces-main:interactive/disp8
61
62 (kernel-string-equal? *(ebp+8) "test")
63 3d/compare-eax-and 0/imm32
64 74/jump-if-equal $subx-braces-main:interactive/disp8
65
66 (run-tests)
67
68 8b/-> *Num-test-failures 3/r32/ebx
69 eb/jump $subx-braces-main:end/disp8
70 $subx-braces-main:interactive:
71 (subx-braces Stdin Stdout)
72
73 bb/copy-to-ebx 0/imm32
74 $subx-braces-main:end:
75 b8/copy-to-eax 1/imm32/exit
76 cd/syscall 0x80/imm8
77
78 subx-braces:
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115 55/push-ebp
116 89/<- %ebp 4/r32/esp
117
118 50/push-eax
119 51/push-ecx
120 52/push-edx
121 53/push-ebx
122 56/push-esi
123 57/push-edi
124
125 8b/-> *(ebp+8) 6/r32/esi
126
127 81 5/subop/subtract %esp 0x200/imm32
128 68/push 0x200/imm32/length
129 68/push 0/imm32/read
130 68/push 0/imm32/write
131 89/<- %ecx 4/r32/esp
132
133 81 5/subop/subtract %esp 0x80/imm32
134 68/push 0x80/imm32/length
135 68/push 0/imm32/top
136 89/<- %edx 4/r32/esp
137
138 c7 0/subop/copy %ebx 1/imm32
139
140 68/push 0/imm32/end
141 68/push 0/imm32/start
142 89/<- %edi 4/r32/esp
143 $subx-braces:line-loop:
144 (clear-stream %ecx)
145 (read-line-buffered %esi %ecx)
146 $subx-braces:check0:
147
148 81 7/subop/compare *ecx 0/imm32
149 0f 84/jump-if-equal $subx-braces:break/disp32
150 (skip-chars-matching-whitespace %ecx)
151 $subx-braces:check-for-curly-open:
152
153
154 8b/-> *(ecx+4) 0/r32/eax
155 8a/copy-byte *(ecx+eax+0xc) 0/r32/AL
156 81 4/subop/and %eax 0xff/imm32
157
158 3d/compare-eax-and 0x7b/imm32/open-curly
159 0f 85/jump-if-not-equal $subx-braces:check-for-curly-closed/disp32
160 $subx-braces:emit-curly-open:
161
162 (write-buffered *(ebp+0xc) "_loop")
163 (print-int32-buffered *(ebp+0xc) %ebx)
164 (write-buffered *(ebp+0xc) ":")
165
166 (push %edx %ebx)
167
168 ff 0/subop/increment %ebx
169
170 e9/jump $subx-braces:next-line/disp32
171 $subx-braces:check-for-curly-closed:
172
173 3d/compare-eax-and 0x7d/imm32/close-curly
174 0f 85/jump-if-equal $subx-braces:word-loop/disp32
175 $subx-braces:emit-curly-closed:
176
177 (pop %edx)
178
179 (write-buffered *(ebp+0xc) "_break")
180 (print-int32-buffered *(ebp+0xc) %eax)
181 (write-buffered *(ebp+0xc) ":")
182
183 e9/jump $subx-braces:next-line/disp32
184 $subx-braces:word-loop:
185 (next-word-or-string %ecx %edi)
186 $subx-braces:check1:
187
188 (slice-empty? %edi)
189 3d/compare-eax-and 0/imm32
190 0f 85/jump-if-not-equal $subx-braces:next-line/disp32
191 $subx-braces:check-for-comment:
192
193
194 8b/-> *edi 0/r32/eax
195 8a/copy-byte *eax 0/r32/AL
196 81 4/subop/and %eax 0xff/imm32
197
198 3d/compare-eax-and 0x23/imm32/hash
199 74/jump-if-equal $subx-braces:word-loop/disp8
200 $subx-braces:check-for-break:
201
202
203 (slice-starts-with? %edi "break/")
204
205 3d/compare-eax-and 0/imm32
206 74/jump-if-equal $subx-braces:check-for-loop/disp8
207 $subx-braces:emit-break:
208 (top %edx)
209
210 (write-buffered *(ebp+0xc) "_break")
211 (print-int32-buffered *(ebp+0xc) %eax)
212
213 81 0/subop/add *edi 5/imm32/strlen
214
215 eb/jump $subx-braces:emit-word-slice/disp8
216 $subx-braces:check-for-loop:
217
218
219 (slice-starts-with? %edi "loop/")
220
221 3d/compare-eax-and 0/imm32
222 74/jump-if-equal $subx-braces:emit-word-slice/disp8
223 $subx-braces:emit-loop:
224 (top %edx)
225
226 (write-buffered *(ebp+0xc) "_loop")
227 (print-int32-buffered *(ebp+0xc) %eax)
228
229 81 0/subop/add *edi 4/imm32/strlen
230
231 $subx-braces:emit-word-slice:
232
233 (write-slice-buffered *(ebp+0xc) %edi)
234 (write-buffered *(ebp+0xc) Space)
235
236 e9/jump $subx-braces:word-loop/disp32
237 $subx-braces:next-line:
238
239 (write-buffered *(ebp+0xc) Newline)
240
241 e9/jump $subx-braces:line-loop/disp32
242 $subx-braces:break:
243 (flush *(ebp+0xc))
244 $subx-braces:end:
245
246 81 0/subop/add %esp 0x29c/imm32
247
248 5f/pop-to-edi
249 5e/pop-to-esi
250 5b/pop-to-ebx
251 5a/pop-to-edx
252 59/pop-to-ecx
253 58/pop-to-eax
254
255 89/<- %esp 5/r32/ebp
256 5d/pop-to-ebp
257 c3/return
258
259 test-subx-braces-passes-most-words-through:
260
261 55/push-ebp
262 89/<- %ebp 4/r32/esp
263
264 (clear-stream _test-input-stream)
265 (clear-stream _test-output-stream)
266
267 b8/copy-to-eax _test-input-buffered-file/imm32
268 05/add-to-eax 4/imm32
269 (clear-stream %eax)
270
271 b8/copy-to-eax _test-output-buffered-file/imm32
272 05/add-to-eax 4/imm32
273 (clear-stream %eax)
274
275 (write _test-input-stream "== abcd 0x1")
276 (subx-braces _test-input-buffered-file _test-output-buffered-file)
277
278 (flush _test-output-buffered-file)
279 +-- 5 lines: #? # dump _test-output-stream --------------------------------------------------------------------------------------------------------------
284 (check-stream-equal _test-output-stream "== abcd 0x1 \n" "F - test-subx-braces-passes-most-words-through")
285
286 89/<- %esp 5/r32/ebp
287 5d/pop-to-ebp
288 c3/return
289
290 test-subx-braces-1:
291
292
293
294
295
296
297
298
299
300
301
302
303
304 55/push-ebp
305 89/<- %ebp 4/r32/esp
306
307 (clear-stream _test-input-stream)
308 (clear-stream _test-output-stream)
309
310 b8/copy-to-eax _test-input-buffered-file/imm32
311 05/add-to-eax 4/imm32
312 (clear-stream %eax)
313
314 b8/copy-to-eax _test-output-buffered-file/imm32
315 05/add-to-eax 4/imm32
316 (clear-stream %eax)
317
318 (write _test-input-stream "{\nab break/imm32\ncd loop/imm32\n}")
319 (subx-braces _test-input-buffered-file _test-output-buffered-file)
320
321 (flush _test-output-buffered-file)
322 +-- 5 lines: #? # dump _test-output-stream --------------------------------------------------------------------------------------------------------------
327 (check-stream-equal _test-output-stream "_loop0x00000001:\nab _break0x00000001/imm32 \ncd _loop0x00000001/imm32 \n_break0x00000001:\n" "F - test-subx-braces-1")
328
329 89/<- %esp 5/r32/ebp
330 5d/pop-to-ebp
331 c3/return
332
333 test-subx-braces-2:
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351 55/push-ebp
352 89/<- %ebp 4/r32/esp
353
354 (clear-stream _test-input-stream)
355 (clear-stream _test-output-stream)
356
357 b8/copy-to-eax _test-input-buffered-file/imm32
358 05/add-to-eax 4/imm32
359 (clear-stream %eax)
360
361 b8/copy-to-eax _test-output-buffered-file/imm32
362 05/add-to-eax 4/imm32
363 (clear-stream %eax)
364
365 (write _test-input-stream "{\n{\nab break/imm32\n}\ncd loop/imm32\n}")
366 (subx-braces _test-input-buffered-file _test-output-buffered-file)
367
368 (flush _test-output-buffered-file)
369 +-- 5 lines: #? # dump _test-output-stream --------------------------------------------------------------------------------------------------------------
374 (check-stream-equal _test-output-stream "_loop0x00000001:\n_loop0x00000002:\nab _break0x00000002/imm32 \n_break0x00000002:\ncd _loop0x00000001/imm32 \n_break0x00000001:\n" "F - test-subx-braces-2")
375
376 89/<- %esp 5/r32/ebp
377 5d/pop-to-ebp
378 c3/return
379
380
381
382
383
384
385
386
387 clear-stack:
388
389 55/push-ebp
390 89/<- %ebp 4/r32/esp
391
392 50/push-eax
393 51/push-ecx
394
395 8b/-> *(ebp+8) 0/r32/eax
396
397 8b/-> *(eax+4) 1/r32/ecx
398
399 8d/copy-address *(eax+ecx+8) 1/r32/ecx
400
401 c7/copy 0/subop/copy *eax 0/imm32
402
403 81 0/subop/add %eax 8/imm32
404 $clear-stack:loop:
405
406 39/compare %eax 1/r32/ecx
407 73/jump-if-greater-or-equal-unsigned $clear-stack:end/disp8
408
409 c6 0/subop/copy-byte *eax 0/imm8
410
411 40/increment-eax
412 eb/jump $clear-stack:loop/disp8
413 $clear-stack:end:
414
415 59/pop-to-ecx
416 58/pop-to-eax
417
418 89/<- %esp 5/r32/ebp
419 5d/pop-to-ebp
420 c3/return
421
422 test-clear-stack:
423
424 68/push 34/imm32
425 68/push 35/imm32
426 68/push 8/imm32/length
427 68/push 14/imm32/top
428 89/<- %ecx 4/r32/esp
429
430 (clear-stack %ecx)
431
432 58/pop-to-eax
433 (check-ints-equal %eax 0 "F - test-clear-stack: top")
434
435 58/pop-to-eax
436 (check-ints-equal %eax 8 "F - test-clear-stack: length")
437
438 58/pop-to-eax
439 (check-ints-equal %eax 0 "F - test-clear-stack: data[0..3]")
440
441 58/pop-to-eax
442 (check-ints-equal %eax 0 "F - test-clear-stack: data[4..7]")
443 c3/return
444
445 push:
446
447 55/push-ebp
448 89/<- %ebp 4/r32/esp
449
450 50/push-eax
451 51/push-ecx
452 56/push-esi
453
454 8b/-> *(ebp+8) 6/r32/esi
455
456 8b/-> *esi 1/r32/ecx
457
458 39/compare *(esi+4) 1/r32/ecx
459 7e/jump-if-lesser-or-equal $push:abort/disp8
460
461 8b/-> *(ebp+0xc) 0/r32/eax
462 89/<- *(esi+ecx+8) 0/r32/eax
463
464 81 0/subop/add *esi 4/imm32
465 $push:end:
466
467 5e/pop-to-esi
468 59/pop-to-ecx
469 58/pop-to-eax
470
471 89/<- %esp 5/r32/ebp
472 5d/pop-to-ebp
473 c3/return
474
475 $push:abort:
476
477
478
479 68/push "error: push: no space left"/imm32
480 68/push Stderr/imm32
481
482 e8/call write-buffered/disp32
483
484 81 0/subop/add %esp 8/imm32
485
486
487 68/push Stderr/imm32
488
489 e8/call flush/disp32
490
491 81 0/subop/add %esp 4/imm32
492
493 bb/copy-to-ebx 1/imm32
494 b8/copy-to-eax 1/imm32/exit
495 cd/syscall 0x80/imm8
496
497
498 test-push:
499
500 68/push 0/imm32
501 68/push 0/imm32
502 68/push 8/imm32/length
503 68/push 0/imm32/top
504 89/<- %ecx 4/r32/esp
505
506 (push %ecx 42)
507
508 58/pop-to-eax
509 (check-ints-equal %eax 4 "F - test-push: top")
510
511 58/pop-to-eax
512 (check-ints-equal %eax 8 "F - test-push: length")
513
514 58/pop-to-eax
515 (check-ints-equal %eax 42 "F - test-push: data[0..3]")
516
517 58/pop-to-eax
518 (check-ints-equal %eax 0 "F - test-push: data[4..7]")
519 c3/return
520
521 pop:
522
523 55/push-ebp
524 89/<- %ebp 4/r32/esp
525
526 51/push-ecx
527 56/push-esi
528
529 8b/-> *(ebp+8) 6/r32/esi
530
531 81 7/subop/compare *esi 0/imm32
532 7e/jump-if-lesser-or-equal $pop:abort/disp8
533
534 81 5/subop/subtract *esi 4/imm32
535
536 8b/-> *esi 1/r32/ecx/top
537 8b/-> *(esi+ecx+8) 0/r32/eax
538 $pop:end:
539
540 5e/pop-to-esi
541 59/pop-to-ecx
542
543 89/<- %esp 5/r32/ebp
544 5d/pop-to-ebp
545 c3/return
546
547 $pop:abort:
548
549
550
551 68/push "error: pop: nothing left in stack"/imm32
552 68/push Stderr/imm32
553
554 e8/call write-buffered/disp32
555
556 81 0/subop/add %esp 8/imm32
557
558
559 68/push Stderr/imm32
560
561 e8/call flush/disp32
562
563 81 0/subop/add %esp 4/imm32
564
565 bb/copy-to-ebx 1/imm32
566 b8/copy-to-eax 1/imm32/exit
567 cd/syscall 0x80/imm8
568
569
570 test-pop:
571
572 68/push 0/imm32
573 68/push 42/imm32
574 68/push 8/imm32/length
575 68/push 4/imm32/top
576 89/<- %ecx 4/r32/esp
577
578 (pop %ecx)
579
580 (check-ints-equal %eax 42 "F - test-pop: result")
581
582 58/pop-to-eax
583 (check-ints-equal %eax 0 "F - test-pop: top")
584
585 58/pop-to-eax
586 (check-ints-equal %eax 8 "F - test-pop: length")
587
588 81 0/subop/add %esp 8/imm32
589 c3/return
590
591 top:
592
593 55/push-ebp
594 89/<- %ebp 4/r32/esp
595
596 51/push-ecx
597 56/push-esi
598
599 8b/-> *(ebp+8) 6/r32/esi
600
601 81 7/subop/compare *esi 0/imm32
602 7e/jump-if-lesser-or-equal $top:abort/disp8
603
604 8b/-> *esi 1/r32/ecx/top
605 81 5/subop/subtract %ecx 4/imm32
606 8b/-> *(esi+ecx+8) 0/r32/eax
607 $top:end:
608
609 5e/pop-to-esi
610 59/pop-to-ecx
611
612 89/<- %esp 5/r32/ebp
613 5d/pop-to-ebp
614 c3/return
615
616 $top:abort:
617
618
619
620 68/push "error: top: nothing left in stack"/imm32
621 68/push Stderr/imm32
622
623 e8/call write-buffered/disp32
624
625 81 0/subop/add %esp 8/imm32
626
627
628 68/push Stderr/imm32
629
630 e8/call flush/disp32
631
632 81 0/subop/add %esp 4/imm32
633
634 bb/copy-to-ebx 1/imm32
635 b8/copy-to-eax 1/imm32/exit
636 cd/syscall 0x80/imm8
637
638
639 test-top:
640
641 68/push 0/imm32
642 68/push 42/imm32
643 68/push 8/imm32/length
644 68/push 4/imm32/top
645 89/<- %ecx 4/r32/esp
646
647 (top %ecx)
648
649 (check-ints-equal %eax 42 "F - test-top: result")
650
651 81 0/subop/add %esp 0x10/imm32
652 c3/return