From 9a77780158842db6e4aa098f5027e030fc3bd878 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Fri, 22 May 2020 23:08:09 -0700 Subject: 6384 --- html/092stack.subx.html | 834 ++++++++++++++++++++++++------------------------ 1 file changed, 420 insertions(+), 414 deletions(-) (limited to 'html/092stack.subx.html') diff --git a/html/092stack.subx.html b/html/092stack.subx.html index 4ccbbe55..7fa5461a 100644 --- a/html/092stack.subx.html +++ b/html/092stack.subx.html @@ -16,13 +16,13 @@ a { color:inherit; } * { font-size:12pt; font-size: 1em; } .subxComment { color: #005faf; } .subxS2Comment { color: #8a8a8a; } +.subxTest { color: #5f8700; } +.subxFunction { color: #af5f00; text-decoration: underline; } .LineNr { } -.SpecialChar { color: #d70000; } .subxS1Comment { color: #0000af; } -.subxFunction { color: #af5f00; text-decoration: underline; } +.SpecialChar { color: #d70000; } .Normal { color: #000000; background-color: #c6c6c6; padding-bottom: 1px; } .Constant { color: #008787; } -.subxTest { color: #5f8700; } --> @@ -60,417 +60,423 @@ if ('onhashchange' in window) {
   1 # A stack looks like this:
   2 #   top: int
-  3 #   data: (array byte)  # prefixed by length as usual
-  4 
-  5 == code
-  6 #   instruction                     effective address                                                   register    displacement    immediate
-  7 # . op          subop               mod             rm32          base        index         scale       r32
-  8 # . 1-3 bytes   3 bits              2 bits          3 bits        3 bits      3 bits        2 bits      2 bits      0/1/2/4 bytes   0/1/2/4 bytes
-  9 
- 10 clear-stack:  # s: (addr stack)
- 11     # . prologue
- 12     55/push-ebp
- 13     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
- 14     # . save registers
- 15     50/push-eax
- 16     51/push-ecx
- 17     # eax = s
- 18     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           0/r32/eax   8/disp8         .                 # copy *(ebp+8) to eax
- 19     # var max/ecx: (addr byte) = &s->data[s->length]
- 20     8b/copy                         1/mod/*+disp8   0/rm32/eax    .           .             .           1/r32/ecx   4/disp8         .                 # copy *(eax+4) to eax
- 21     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    0/base/eax  1/index/ecx   .           1/r32/ecx   8/disp8         .                 # copy eax+ecx+8 to ecx
- 22     # s->top = 0
- 23     c7          0/subop/copy        0/mod/direct    0/rm32/eax    .           .             .           .           .               0/imm32           # copy to *eax
- 24     # var curr/eax: (addr byte) = s->data
- 25     81          0/subop/add         3/mod/direct    0/rm32/eax    .           .             .           .           .               8/imm32           # add to eax
- 26 $clear-stack:loop:
- 27     # if (curr >= max) break
- 28     39/compare                      3/mod/direct    0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # compare eax with ecx
- 29     73/jump-if-addr>=  $clear-stack:end/disp8
- 30     # *curr = 0
- 31     c6          0/subop/copy        0/mod/direct    0/rm32/eax    .           .             .           .           .               0/imm8            # copy byte to *eax
- 32     # ++curr
- 33     40/increment-eax
- 34     eb/jump $clear-stack:loop/disp8
- 35 $clear-stack:end:
- 36     # . restore registers
- 37     59/pop-to-ecx
- 38     58/pop-to-eax
- 39     # . epilogue
- 40     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
- 41     5d/pop-to-ebp
- 42     c3/return
- 43 
- 44 test-clear-stack:
- 45     # . prologue
- 46     55/push-ebp
- 47     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
- 48     # var stack/ecx = stack of size 8 with random data in it
- 49     68/push 34/imm32
- 50     68/push 35/imm32
- 51     68/push 8/imm32/length
- 52     68/push 14/imm32/top
- 53     89/copy                         3/mod/direct    1/rm32/ecx    .           .             .           4/r32/esp   .               .                 # copy esp to ecx
- 54     # clear(stack)
- 55     # . . push args
- 56     51/push-ecx
- 57     # . . call
- 58     e8/call  clear-stack/disp32
- 59     # . . discard args
- 60     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
- 61     # top should be 0
- 62     58/pop-to-eax
- 63     # . check-ints-equal(eax, 0, msg)
- 64     # . . push args
- 65     68/push  "F - test-clear-stack: top"/imm32
- 66     68/push  0/imm32
- 67     50/push-eax
- 68     # . . call
- 69     e8/call  check-ints-equal/disp32
- 70     # . . discard args
- 71     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
- 72     # length should remain 8
- 73     58/pop-to-eax
- 74     # . check-ints-equal(eax, 8, msg)
- 75     # . . push args
- 76     68/push  "F - test-clear-stack: length"/imm32
- 77     68/push  8/imm32
- 78     50/push-eax
- 79     # . . call
- 80     e8/call  check-ints-equal/disp32
- 81     # . . discard args
- 82     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
- 83     # first word is 0
- 84     58/pop-to-eax
- 85     # . check-ints-equal(eax, 0, msg)
- 86     # . . push args
- 87     68/push  "F - test-clear-stack: data[0..3]"/imm32
- 88     68/push  0/imm32
- 89     50/push-eax
- 90     # . . call
- 91     e8/call  check-ints-equal/disp32
- 92     # . . discard args
- 93     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
- 94     # second word is 0
- 95     58/pop-to-eax
- 96     # . check-ints-equal(eax, 0, msg)
- 97     # . . push args
- 98     68/push  "F - test-clear-stack: data[4..7]"/imm32
- 99     68/push  0/imm32
-100     50/push-eax
-101     # . . call
-102     e8/call  check-ints-equal/disp32
-103     # . . discard args
-104     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-105     # . epilogue
-106     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
-107     5d/pop-to-ebp
-108     c3/return
-109 
-110 push:  # s: (addr stack), n: int
-111     # . prologue
-112     55/push-ebp
-113     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
-114     # . save registers
-115     50/push-eax
-116     51/push-ecx
-117     56/push-esi
-118     # esi = s
-119     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   8/disp8         .                 # copy *(ebp+8) to esi
-120     # ecx = s->top
-121     8b/copy                         0/mod/indirect  6/rm32/esi    .           .             .           1/r32/ecx   .               .                 # copy *esi to ecx
-122     # if (s->top >= s->length) abort
-123     39/compare                      1/mod/*+disp8   6/rm32/esi    .           .             .           1/r32/ecx   4/disp8         .                 # compare *(esi+4) and ecx
-124     7e/jump-if-<=  $push:abort/disp8
-125     # s->data[s->top] = n
-126     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           0/r32/eax   0xc/disp8       .                 # copy *(ebp+12) to eax
-127     89/copy                         1/mod/*+disp8   4/rm32/sib    6/base/esi  1/index/ecx   .           0/r32/eax   8/disp8         .                 # copy eax to *(esi+ecx+8)
-128     # s->top += 4
-129     81          0/subop/add         0/mod/direct    6/rm32/esi    .           .             .           .           .               4/imm32           # subtract from *esi
-130 $push:end:
-131     # . restore registers
-132     5e/pop-to-esi
-133     59/pop-to-ecx
-134     58/pop-to-eax
-135     # . epilogue
-136     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
-137     5d/pop-to-ebp
-138     c3/return
-139 
-140 $push:abort:
-141     # print(stderr, "error: push: no space left")
-142     # . write-buffered(Stderr, "error: push: no space left")
-143     # . . push args
-144     68/push  "error: push: no space left"/imm32
-145     68/push  Stderr/imm32
-146     # . . call
-147     e8/call  write-buffered/disp32
-148     # . . discard args
-149     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-150     # . flush(Stderr)
-151     # . . push args
-152     68/push  Stderr/imm32
-153     # . . call
-154     e8/call  flush/disp32
-155     # . . discard args
-156     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-157     # . syscall(exit, 1)
-158     bb/copy-to-ebx  1/imm32
-159     b8/copy-to-eax  1/imm32/exit
-160     cd/syscall  0x80/imm8
-161     # never gets here
-162 
-163 test-push:
-164     # . prologue
-165     55/push-ebp
-166     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
-167     # var stack/ecx = empty stack of size 8
-168     68/push 0/imm32
-169     68/push 0/imm32
-170     68/push 8/imm32/length
-171     68/push 0/imm32/top
-172     89/copy                         3/mod/direct    1/rm32/ecx    .           .             .           4/r32/esp   .               .                 # copy esp to ecx
-173     # push(stack, 0x42)
-174     # . . push args
-175     68/push  0x42/imm32
-176     51/push-ecx
-177     # . . call
-178     e8/call  push/disp32
-179     # . . discard args
-180     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-181     # check top
-182     58/pop-to-eax
-183     # . check-ints-equal(eax, 4, msg)
-184     # . . push args
-185     68/push  "F - test-push: top"/imm32
-186     68/push  4/imm32
-187     50/push-eax
-188     # . . call
-189     e8/call  check-ints-equal/disp32
-190     # . . discard args
-191     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-192     # check length
-193     58/pop-to-eax
-194     # . check-ints-equal(eax, 8, msg)
-195     # . . push args
-196     68/push  "F - test-push: length"/imm32
-197     68/push  8/imm32
-198     50/push-eax
-199     # . . call
-200     e8/call  check-ints-equal/disp32
-201     # . . discard args
-202     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-203     # first word is 0x42
-204     58/pop-to-eax
-205     # . check-ints-equal(eax, 0x42, msg)
-206     # . . push args
-207     68/push  "F - test-push: data[0..3]"/imm32
-208     68/push  0x42/imm32
-209     50/push-eax
-210     # . . call
-211     e8/call  check-ints-equal/disp32
-212     # . . discard args
-213     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-214     # second word is 0
-215     58/pop-to-eax
-216     # . check-ints-equal(eax, 0, msg)
-217     # . . push args
-218     68/push  "F - test-push: data[4..7]"/imm32
-219     68/push  0/imm32
-220     50/push-eax
-221     # . . call
-222     e8/call  check-ints-equal/disp32
-223     # . . discard args
-224     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-225     # . epilogue
-226     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
-227     5d/pop-to-ebp
-228     c3/return
-229 
-230 pop:  # s: (addr stack) -> n/eax: int
-231     # . prologue
-232     55/push-ebp
-233     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
-234     # . save registers
-235     51/push-ecx
-236     56/push-esi
-237     # esi = s
-238     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   8/disp8         .                 # copy *(ebp+8) to esi
-239     # if (s->top <= 0) abort
-240     81          7/subop/compare     0/mod/indirect  6/rm32/esi    .           .             .           .           .               0/imm32           # compare *esi
-241     7e/jump-if-<=  $pop:abort/disp8
-242     # s->top -= 4
-243     81          5/subop/subtract    0/mod/direct    6/rm32/esi    .           .             .           .           .               4/imm32           # subtract from *esi
-244     # eax = s->data[s->top]
-245     8b/copy                         0/mod/indirect  6/rm32/esi    .           .             .           1/r32/ecx   .               .                 # copy *esi to ecx
-246     8b/copy                         1/mod/*+disp8   4/rm32/sib    6/base/esi  1/index/ecx   .           0/r32/eax   8/disp8         .                 # copy *(esi+ecx+8) to eax
-247     # s->data[s->top] = 0
-248     c7          0/subop/copy        1/mod/*+disp8   4/rm32/sib    6/base/esi  1/index/ecx   .           0/r32/eax   8/disp8         0/imm32           # copy to *(esi+ecx+8)
-249 $pop:end:
-250     # . restore registers
-251     5e/pop-to-esi
-252     59/pop-to-ecx
-253     # . epilogue
-254     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
-255     5d/pop-to-ebp
-256     c3/return
-257 
-258 $pop:abort:
-259     # print(stderr, "error: pop: nothing left in stack")
-260     # . write-buffered(Stderr, "error: pop: nothing left in stack")
-261     # . . push args
-262     68/push  "error: pop: nothing left in stack"/imm32
-263     68/push  Stderr/imm32
-264     # . . call
-265     e8/call  write-buffered/disp32
-266     # . . discard args
-267     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-268     # . flush(Stderr)
-269     # . . push args
-270     68/push  Stderr/imm32
-271     # . . call
-272     e8/call  flush/disp32
-273     # . . discard args
-274     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-275     # . syscall(exit, 1)
-276     bb/copy-to-ebx  1/imm32
-277     b8/copy-to-eax  1/imm32/exit
-278     cd/syscall  0x80/imm8
-279     # never gets here
-280 
-281 test-pop:
-282     # . prologue
-283     55/push-ebp
-284     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
-285     # var stack/ecx = stack of size 8 containing just 0x42
-286     68/push 0/imm32
-287     68/push 0x42/imm32
-288     68/push 8/imm32/length
-289     68/push 4/imm32/top
-290     89/copy                         3/mod/direct    1/rm32/ecx    .           .             .           4/r32/esp   .               .                 # copy esp to ecx
-291     # eax = pop(stack)
-292     # . . push args
-293     51/push-ecx
-294     # . . call
-295     e8/call  pop/disp32
-296     # . . discard args
-297     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-298     # check-ints-equal(eax, 0x42, msg)
-299     # . . push args
-300     68/push  "F - test-pop: result"/imm32
-301     68/push  0x42/imm32
-302     50/push-eax
-303     # . . call
-304     e8/call  check-ints-equal/disp32
-305     # . . discard args
-306     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-307     # check top
-308     58/pop-to-eax
-309     # . check-ints-equal(eax, 0, msg)
-310     # . . push args
-311     68/push  "F - test-pop: top"/imm32
-312     68/push  0/imm32
-313     50/push-eax
-314     # . . call
-315     e8/call  check-ints-equal/disp32
-316     # . . discard args
-317     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-318     # check length
-319     58/pop-to-eax
-320     # . check-ints-equal(eax, 8, msg)
-321     # . . push args
-322     68/push  "F - test-pop: length"/imm32
-323     68/push  8/imm32
-324     50/push-eax
-325     # . . call
-326     e8/call  check-ints-equal/disp32
-327     # . . discard args
-328     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-329     # . epilogue
-330     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
-331     5d/pop-to-ebp
-332     c3/return
-333 
-334 top:  # s: (addr stack) -> n/eax: int
-335     # . prologue
-336     55/push-ebp
-337     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
-338     # . save registers
-339     51/push-ecx
-340     56/push-esi
-341     # esi = s
-342     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   8/disp8         .                 # copy *(ebp+8) to esi
-343     # if (s->top <= 0) abort
-344     81          7/subop/compare     0/mod/indirect  6/rm32/esi    .           .             .           .           .               0/imm32           # compare *esi
-345     7e/jump-if-<=  $top:abort/disp8
-346     # n = s->data[s->top - 4]
-347     8b/copy                         0/mod/indirect  6/rm32/esi    .           .             .           1/r32/ecx   .               .                 # copy *esi to ecx
-348     81          5/subop/subtract    3/mod/direct    1/rm32/ecx    .           .             .           .           .               4/imm32           # subtract from ecx
-349     8b/copy                         1/mod/*+disp8   4/rm32/sib    6/base/esi  1/index/ecx   .           0/r32/eax   8/disp8         .                 # copy *(esi+ecx+8) to eax
-350 $top:end:
-351     # . restore registers
-352     5e/pop-to-esi
-353     59/pop-to-ecx
-354     # . epilogue
-355     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
-356     5d/pop-to-ebp
-357     c3/return
-358 
-359 $top:abort:
-360     # print(stderr, "error: top: nothing left in stack")
-361     # . write-buffered(Stderr, "error: top: nothing left in stack")
-362     # . . push args
-363     68/push  "error: top: nothing left in stack"/imm32
-364     68/push  Stderr/imm32
-365     # . . call
-366     e8/call  write-buffered/disp32
-367     # . . discard args
-368     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-369     # . flush(Stderr)
-370     # . . push args
-371     68/push  Stderr/imm32
-372     # . . call
-373     e8/call  flush/disp32
-374     # . . discard args
-375     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-376     # . syscall(exit, 1)
-377     bb/copy-to-ebx  1/imm32
-378     b8/copy-to-eax  1/imm32/exit
-379     cd/syscall  0x80/imm8
-380     # never gets here
-381 
-382 test-top:
-383     # . prologue
-384     55/push-ebp
-385     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
-386     # var stack/ecx = stack of size 8 containing just 0x42
-387     68/push  0/imm32
-388     68/push  0x42/imm32
-389     68/push  8/imm32/length
-390     68/push  4/imm32/top
-391     89/copy                         3/mod/direct    1/rm32/ecx    .           .             .           4/r32/esp   .               .                 # copy esp to ecx
-392     # eax = top(stack)
-393     # . . push args
-394     51/push-ecx
-395     # . . call
-396     e8/call  top/disp32
-397     # . . discard args
-398     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-399     # check-ints-equal(eax, 42, msg")
-400     # . . push args
-401     68/push  "F - test-top: result"/imm32
-402     68/push  0x42/imm32
-403     50/push-eax
-404     # . . call
-405     e8/call  check-ints-equal/disp32
-406     # . . discard args
-407     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-408     # . epilogue
-409     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
-410     5d/pop-to-ebp
-411     c3/return
-412 
-413 # . . vim:nowrap:textwidth=0
+  3 #   data: (array byte)  # prefixed by size as usual
+  4 #
+  5 # TODO: is it confusing that the push opcodes grow memory downward, but the
+  6 # push function grows stacks upward?
+  7 
+  8 == code
+  9 #   instruction                     effective address                                                   register    displacement    immediate
+ 10 # . op          subop               mod             rm32          base        index         scale       r32
+ 11 # . 1-3 bytes   3 bits              2 bits          3 bits        3 bits      3 bits        2 bits      2 bits      0/1/2/4 bytes   0/1/2/4 bytes
+ 12 
+ 13 clear-stack:  # s: (addr stack)
+ 14     # . prologue
+ 15     55/push-ebp
+ 16     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+ 17     # . save registers
+ 18     50/push-eax
+ 19     51/push-ecx
+ 20     # eax = s
+ 21     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           0/r32/eax   8/disp8         .                 # copy *(ebp+8) to eax
+ 22     # var max/ecx: (addr byte) = &s->data[s->size]
+ 23     8b/copy                         1/mod/*+disp8   0/rm32/eax    .           .             .           1/r32/ecx   4/disp8         .                 # copy *(eax+4) to eax
+ 24     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    0/base/eax  1/index/ecx   .           1/r32/ecx   8/disp8         .                 # copy eax+ecx+8 to ecx
+ 25     # s->top = 0
+ 26     c7          0/subop/copy        0/mod/direct    0/rm32/eax    .           .             .           .           .               0/imm32           # copy to *eax
+ 27     # var curr/eax: (addr byte) = s->data
+ 28     81          0/subop/add         3/mod/direct    0/rm32/eax    .           .             .           .           .               8/imm32           # add to eax
+ 29 $clear-stack:loop:
+ 30     # if (curr >= max) break
+ 31     39/compare                      3/mod/direct    0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # compare eax with ecx
+ 32     73/jump-if-addr>=  $clear-stack:end/disp8
+ 33     # *curr = 0
+ 34     c6          0/subop/copy        0/mod/direct    0/rm32/eax    .           .             .           .           .               0/imm8            # copy byte to *eax
+ 35     # ++curr
+ 36     40/increment-eax
+ 37     eb/jump $clear-stack:loop/disp8
+ 38 $clear-stack:end:
+ 39     # . restore registers
+ 40     59/pop-to-ecx
+ 41     58/pop-to-eax
+ 42     # . epilogue
+ 43     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+ 44     5d/pop-to-ebp
+ 45     c3/return
+ 46 
+ 47 test-clear-stack:
+ 48     # . prologue
+ 49     55/push-ebp
+ 50     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+ 51     # var stack/ecx = stack of size 8 with random data in it
+ 52     68/push 34/imm32
+ 53     68/push 35/imm32
+ 54     68/push 8/imm32/size
+ 55     68/push 14/imm32/top
+ 56     89/copy                         3/mod/direct    1/rm32/ecx    .           .             .           4/r32/esp   .               .                 # copy esp to ecx
+ 57     # clear(stack)
+ 58     # . . push args
+ 59     51/push-ecx
+ 60     # . . call
+ 61     e8/call  clear-stack/disp32
+ 62     # . . discard args
+ 63     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+ 64     # top should be 0
+ 65     58/pop-to-eax
+ 66     # . check-ints-equal(eax, 0, msg)
+ 67     # . . push args
+ 68     68/push  "F - test-clear-stack: top"/imm32
+ 69     68/push  0/imm32
+ 70     50/push-eax
+ 71     # . . call
+ 72     e8/call  check-ints-equal/disp32
+ 73     # . . discard args
+ 74     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+ 75     # size should remain 8
+ 76     58/pop-to-eax
+ 77     # . check-ints-equal(eax, 8, msg)
+ 78     # . . push args
+ 79     68/push  "F - test-clear-stack: size"/imm32
+ 80     68/push  8/imm32
+ 81     50/push-eax
+ 82     # . . call
+ 83     e8/call  check-ints-equal/disp32
+ 84     # . . discard args
+ 85     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+ 86     # first word is 0
+ 87     58/pop-to-eax
+ 88     # . check-ints-equal(eax, 0, msg)
+ 89     # . . push args
+ 90     68/push  "F - test-clear-stack: data[0..3]"/imm32
+ 91     68/push  0/imm32
+ 92     50/push-eax
+ 93     # . . call
+ 94     e8/call  check-ints-equal/disp32
+ 95     # . . discard args
+ 96     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+ 97     # second word is 0
+ 98     58/pop-to-eax
+ 99     # . check-ints-equal(eax, 0, msg)
+100     # . . push args
+101     68/push  "F - test-clear-stack: data[4..7]"/imm32
+102     68/push  0/imm32
+103     50/push-eax
+104     # . . call
+105     e8/call  check-ints-equal/disp32
+106     # . . discard args
+107     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+108     # . epilogue
+109     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+110     5d/pop-to-ebp
+111     c3/return
+112 
+113 # TODO: make this generic
+114 push:  # s: (addr stack), n: int
+115     # . prologue
+116     55/push-ebp
+117     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+118     # . save registers
+119     50/push-eax
+120     51/push-ecx
+121     56/push-esi
+122     # esi = s
+123     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   8/disp8         .                 # copy *(ebp+8) to esi
+124     # ecx = s->top
+125     8b/copy                         0/mod/indirect  6/rm32/esi    .           .             .           1/r32/ecx   .               .                 # copy *esi to ecx
+126     # if (s->top >= s->size) abort
+127     39/compare                      1/mod/*+disp8   6/rm32/esi    .           .             .           1/r32/ecx   4/disp8         .                 # compare *(esi+4) and ecx
+128     7e/jump-if-<=  $push:abort/disp8
+129     # s->data[s->top] = n
+130     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           0/r32/eax   0xc/disp8       .                 # copy *(ebp+12) to eax
+131     89/copy                         1/mod/*+disp8   4/rm32/sib    6/base/esi  1/index/ecx   .           0/r32/eax   8/disp8         .                 # copy eax to *(esi+ecx+8)
+132     # s->top += 4
+133     81          0/subop/add         0/mod/direct    6/rm32/esi    .           .             .           .           .               4/imm32           # subtract from *esi
+134 $push:end:
+135     # . restore registers
+136     5e/pop-to-esi
+137     59/pop-to-ecx
+138     58/pop-to-eax
+139     # . epilogue
+140     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+141     5d/pop-to-ebp
+142     c3/return
+143 
+144 $push:abort:
+145     # print(stderr, "error: push: no space left")
+146     # . write-buffered(Stderr, "error: push: no space left")
+147     # . . push args
+148     68/push  "error: push: no space left"/imm32
+149     68/push  Stderr/imm32
+150     # . . call
+151     e8/call  write-buffered/disp32
+152     # . . discard args
+153     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+154     # . flush(Stderr)
+155     # . . push args
+156     68/push  Stderr/imm32
+157     # . . call
+158     e8/call  flush/disp32
+159     # . . discard args
+160     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+161     # . syscall(exit, 1)
+162     bb/copy-to-ebx  1/imm32
+163     b8/copy-to-eax  1/imm32/exit
+164     cd/syscall  0x80/imm8
+165     # never gets here
+166 
+167 test-push:
+168     # . prologue
+169     55/push-ebp
+170     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+171     # var stack/ecx = empty stack of size 8
+172     68/push 0/imm32
+173     68/push 0/imm32
+174     68/push 8/imm32/size
+175     68/push 0/imm32/top
+176     89/copy                         3/mod/direct    1/rm32/ecx    .           .             .           4/r32/esp   .               .                 # copy esp to ecx
+177     # push(stack, 0x42)
+178     # . . push args
+179     68/push  0x42/imm32
+180     51/push-ecx
+181     # . . call
+182     e8/call  push/disp32
+183     # . . discard args
+184     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+185     # check top
+186     58/pop-to-eax
+187     # . check-ints-equal(eax, 4, msg)
+188     # . . push args
+189     68/push  "F - test-push: top"/imm32
+190     68/push  4/imm32
+191     50/push-eax
+192     # . . call
+193     e8/call  check-ints-equal/disp32
+194     # . . discard args
+195     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+196     # check size
+197     58/pop-to-eax
+198     # . check-ints-equal(eax, 8, msg)
+199     # . . push args
+200     68/push  "F - test-push: size"/imm32
+201     68/push  8/imm32
+202     50/push-eax
+203     # . . call
+204     e8/call  check-ints-equal/disp32
+205     # . . discard args
+206     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+207     # first word is 0x42
+208     58/pop-to-eax
+209     # . check-ints-equal(eax, 0x42, msg)
+210     # . . push args
+211     68/push  "F - test-push: data[0..3]"/imm32
+212     68/push  0x42/imm32
+213     50/push-eax
+214     # . . call
+215     e8/call  check-ints-equal/disp32
+216     # . . discard args
+217     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+218     # second word is 0
+219     58/pop-to-eax
+220     # . check-ints-equal(eax, 0, msg)
+221     # . . push args
+222     68/push  "F - test-push: data[4..7]"/imm32
+223     68/push  0/imm32
+224     50/push-eax
+225     # . . call
+226     e8/call  check-ints-equal/disp32
+227     # . . discard args
+228     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+229     # . epilogue
+230     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+231     5d/pop-to-ebp
+232     c3/return
+233 
+234 # TODO: make this generic
+235 pop:  # s: (addr stack) -> n/eax: int
+236     # . prologue
+237     55/push-ebp
+238     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+239     # . save registers
+240     51/push-ecx
+241     56/push-esi
+242     # esi = s
+243     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   8/disp8         .                 # copy *(ebp+8) to esi
+244     # if (s->top <= 0) abort
+245     81          7/subop/compare     0/mod/indirect  6/rm32/esi    .           .             .           .           .               0/imm32           # compare *esi
+246     7e/jump-if-<=  $pop:abort/disp8
+247     # s->top -= 4
+248     81          5/subop/subtract    0/mod/direct    6/rm32/esi    .           .             .           .           .               4/imm32           # subtract from *esi
+249     # eax = s->data[s->top]
+250     8b/copy                         0/mod/indirect  6/rm32/esi    .           .             .           1/r32/ecx   .               .                 # copy *esi to ecx
+251     8b/copy                         1/mod/*+disp8   4/rm32/sib    6/base/esi  1/index/ecx   .           0/r32/eax   8/disp8         .                 # copy *(esi+ecx+8) to eax
+252     # s->data[s->top] = 0
+253     c7          0/subop/copy        1/mod/*+disp8   4/rm32/sib    6/base/esi  1/index/ecx   .           0/r32/eax   8/disp8         0/imm32           # copy to *(esi+ecx+8)
+254 $pop:end:
+255     # . restore registers
+256     5e/pop-to-esi
+257     59/pop-to-ecx
+258     # . epilogue
+259     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+260     5d/pop-to-ebp
+261     c3/return
+262 
+263 $pop:abort:
+264     # print(stderr, "error: pop: nothing left in stack")
+265     # . write-buffered(Stderr, "error: pop: nothing left in stack")
+266     # . . push args
+267     68/push  "error: pop: nothing left in stack"/imm32
+268     68/push  Stderr/imm32
+269     # . . call
+270     e8/call  write-buffered/disp32
+271     # . . discard args
+272     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+273     # . flush(Stderr)
+274     # . . push args
+275     68/push  Stderr/imm32
+276     # . . call
+277     e8/call  flush/disp32
+278     # . . discard args
+279     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+280     # . syscall(exit, 1)
+281     bb/copy-to-ebx  1/imm32
+282     b8/copy-to-eax  1/imm32/exit
+283     cd/syscall  0x80/imm8
+284     # never gets here
+285 
+286 test-pop:
+287     # . prologue
+288     55/push-ebp
+289     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+290     # var stack/ecx = stack of size 8 containing just 0x42
+291     68/push 0/imm32
+292     68/push 0x42/imm32
+293     68/push 8/imm32/size
+294     68/push 4/imm32/top
+295     89/copy                         3/mod/direct    1/rm32/ecx    .           .             .           4/r32/esp   .               .                 # copy esp to ecx
+296     # eax = pop(stack)
+297     # . . push args
+298     51/push-ecx
+299     # . . call
+300     e8/call  pop/disp32
+301     # . . discard args
+302     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+303     # check-ints-equal(eax, 0x42, msg)
+304     # . . push args
+305     68/push  "F - test-pop: result"/imm32
+306     68/push  0x42/imm32
+307     50/push-eax
+308     # . . call
+309     e8/call  check-ints-equal/disp32
+310     # . . discard args
+311     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+312     # check top
+313     58/pop-to-eax
+314     # . check-ints-equal(eax, 0, msg)
+315     # . . push args
+316     68/push  "F - test-pop: top"/imm32
+317     68/push  0/imm32
+318     50/push-eax
+319     # . . call
+320     e8/call  check-ints-equal/disp32
+321     # . . discard args
+322     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+323     # check size
+324     58/pop-to-eax
+325     # . check-ints-equal(eax, 8, msg)
+326     # . . push args
+327     68/push  "F - test-pop: size"/imm32
+328     68/push  8/imm32
+329     50/push-eax
+330     # . . call
+331     e8/call  check-ints-equal/disp32
+332     # . . discard args
+333     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+334     # . epilogue
+335     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+336     5d/pop-to-ebp
+337     c3/return
+338 
+339 # TODO: make this generic
+340 top:  # s: (addr stack) -> n/eax: int
+341     # . prologue
+342     55/push-ebp
+343     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+344     # . save registers
+345     51/push-ecx
+346     56/push-esi
+347     # esi = s
+348     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   8/disp8         .                 # copy *(ebp+8) to esi
+349     # if (s->top <= 0) abort
+350     81          7/subop/compare     0/mod/indirect  6/rm32/esi    .           .             .           .           .               0/imm32           # compare *esi
+351     7e/jump-if-<=  $top:abort/disp8
+352     # n = s->data[s->top - 4]
+353     8b/copy                         0/mod/indirect  6/rm32/esi    .           .             .           1/r32/ecx   .               .                 # copy *esi to ecx
+354     81          5/subop/subtract    3/mod/direct    1/rm32/ecx    .           .             .           .           .               4/imm32           # subtract from ecx
+355     8b/copy                         1/mod/*+disp8   4/rm32/sib    6/base/esi  1/index/ecx   .           0/r32/eax   8/disp8         .                 # copy *(esi+ecx+8) to eax
+356 $top:end:
+357     # . restore registers
+358     5e/pop-to-esi
+359     59/pop-to-ecx
+360     # . epilogue
+361     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+362     5d/pop-to-ebp
+363     c3/return
+364 
+365 $top:abort:
+366     # print(stderr, "error: top: nothing left in stack")
+367     # . write-buffered(Stderr, "error: top: nothing left in stack")
+368     # . . push args
+369     68/push  "error: top: nothing left in stack"/imm32
+370     68/push  Stderr/imm32
+371     # . . call
+372     e8/call  write-buffered/disp32
+373     # . . discard args
+374     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+375     # . flush(Stderr)
+376     # . . push args
+377     68/push  Stderr/imm32
+378     # . . call
+379     e8/call  flush/disp32
+380     # . . discard args
+381     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+382     # . syscall(exit, 1)
+383     bb/copy-to-ebx  1/imm32
+384     b8/copy-to-eax  1/imm32/exit
+385     cd/syscall  0x80/imm8
+386     # never gets here
+387 
+388 test-top:
+389     # . prologue
+390     55/push-ebp
+391     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+392     # var stack/ecx = stack of size 8 containing just 0x42
+393     68/push  0/imm32
+394     68/push  0x42/imm32
+395     68/push  8/imm32/size
+396     68/push  4/imm32/top
+397     89/copy                         3/mod/direct    1/rm32/ecx    .           .             .           4/r32/esp   .               .                 # copy esp to ecx
+398     # eax = top(stack)
+399     # . . push args
+400     51/push-ecx
+401     # . . call
+402     e8/call  top/disp32
+403     # . . discard args
+404     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+405     # check-ints-equal(eax, 42, msg")
+406     # . . push args
+407     68/push  "F - test-top: result"/imm32
+408     68/push  0x42/imm32
+409     50/push-eax
+410     # . . call
+411     e8/call  check-ints-equal/disp32
+412     # . . discard args
+413     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+414     # . epilogue
+415     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+416     5d/pop-to-ebp
+417     c3/return
+418 
+419 # . . vim:nowrap:textwidth=0
 
-- cgit 1.4.1-2-gfad0