From ec73ed1230d75deb0f913a32617c9f1e0a5ca640 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Fri, 10 Jul 2020 23:44:10 -0700 Subject: 6631 --- html/203stack.subx.html | 480 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 480 insertions(+) create mode 100644 html/203stack.subx.html (limited to 'html/203stack.subx.html') diff --git a/html/203stack.subx.html b/html/203stack.subx.html new file mode 100644 index 00000000..b32c4143 --- /dev/null +++ b/html/203stack.subx.html @@ -0,0 +1,480 @@ + + + + +Mu - 203stack.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/203stack.subx +
+  1 # A stack looks like this:
+  2 #   top: int
+  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     e8/call  syscall_exit/disp32
+164     # never gets here
+165 
+166 test-push:
+167     # . prologue
+168     55/push-ebp
+169     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+170     # var stack/ecx = empty stack of size 8
+171     68/push 0/imm32
+172     68/push 0/imm32
+173     68/push 8/imm32/size
+174     68/push 0/imm32/top
+175     89/copy                         3/mod/direct    1/rm32/ecx    .           .             .           4/r32/esp   .               .                 # copy esp to ecx
+176     # push(stack, 0x42)
+177     # . . push args
+178     68/push  0x42/imm32
+179     51/push-ecx
+180     # . . call
+181     e8/call  push/disp32
+182     # . . discard args
+183     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+184     # check top
+185     58/pop-to-eax
+186     # . check-ints-equal(eax, 4, msg)
+187     # . . push args
+188     68/push  "F - test-push: top"/imm32
+189     68/push  4/imm32
+190     50/push-eax
+191     # . . call
+192     e8/call  check-ints-equal/disp32
+193     # . . discard args
+194     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+195     # check size
+196     58/pop-to-eax
+197     # . check-ints-equal(eax, 8, msg)
+198     # . . push args
+199     68/push  "F - test-push: size"/imm32
+200     68/push  8/imm32
+201     50/push-eax
+202     # . . call
+203     e8/call  check-ints-equal/disp32
+204     # . . discard args
+205     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+206     # first word is 0x42
+207     58/pop-to-eax
+208     # . check-ints-equal(eax, 0x42, msg)
+209     # . . push args
+210     68/push  "F - test-push: data[0..3]"/imm32
+211     68/push  0x42/imm32
+212     50/push-eax
+213     # . . call
+214     e8/call  check-ints-equal/disp32
+215     # . . discard args
+216     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+217     # second word is 0
+218     58/pop-to-eax
+219     # . check-ints-equal(eax, 0, msg)
+220     # . . push args
+221     68/push  "F - test-push: data[4..7]"/imm32
+222     68/push  0/imm32
+223     50/push-eax
+224     # . . call
+225     e8/call  check-ints-equal/disp32
+226     # . . discard args
+227     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+228     # . epilogue
+229     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+230     5d/pop-to-ebp
+231     c3/return
+232 
+233 # TODO: make this generic
+234 pop:  # s: (addr stack) -> n/eax: int
+235     # . prologue
+236     55/push-ebp
+237     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+238     # . save registers
+239     51/push-ecx
+240     56/push-esi
+241     # esi = s
+242     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   8/disp8         .                 # copy *(ebp+8) to esi
+243     # if (s->top <= 0) abort
+244     81          7/subop/compare     0/mod/indirect  6/rm32/esi    .           .             .           .           .               0/imm32           # compare *esi
+245     7e/jump-if-<=  $pop:abort/disp8
+246     # s->top -= 4
+247     81          5/subop/subtract    0/mod/direct    6/rm32/esi    .           .             .           .           .               4/imm32           # subtract from *esi
+248     # eax = s->data[s->top]
+249     8b/copy                         0/mod/indirect  6/rm32/esi    .           .             .           1/r32/ecx   .               .                 # copy *esi to ecx
+250     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
+251     # s->data[s->top] = 0
+252     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)
+253 $pop:end:
+254     # . restore registers
+255     5e/pop-to-esi
+256     59/pop-to-ecx
+257     # . epilogue
+258     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+259     5d/pop-to-ebp
+260     c3/return
+261 
+262 $pop:abort:
+263     # print(stderr, "error: pop: nothing left in stack")
+264     # . write-buffered(Stderr, "error: pop: nothing left in stack")
+265     # . . push args
+266     68/push  "error: pop: nothing left in stack"/imm32
+267     68/push  Stderr/imm32
+268     # . . call
+269     e8/call  write-buffered/disp32
+270     # . . discard args
+271     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+272     # . flush(Stderr)
+273     # . . push args
+274     68/push  Stderr/imm32
+275     # . . call
+276     e8/call  flush/disp32
+277     # . . discard args
+278     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+279     # . syscall(exit, 1)
+280     bb/copy-to-ebx  1/imm32
+281     e8/call  syscall_exit/disp32
+282     # never gets here
+283 
+284 test-pop:
+285     # . prologue
+286     55/push-ebp
+287     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+288     # var stack/ecx = stack of size 8 containing just 0x42
+289     68/push 0/imm32
+290     68/push 0x42/imm32
+291     68/push 8/imm32/size
+292     68/push 4/imm32/top
+293     89/copy                         3/mod/direct    1/rm32/ecx    .           .             .           4/r32/esp   .               .                 # copy esp to ecx
+294     # eax = pop(stack)
+295     # . . push args
+296     51/push-ecx
+297     # . . call
+298     e8/call  pop/disp32
+299     # . . discard args
+300     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+301     # check-ints-equal(eax, 0x42, msg)
+302     # . . push args
+303     68/push  "F - test-pop: result"/imm32
+304     68/push  0x42/imm32
+305     50/push-eax
+306     # . . call
+307     e8/call  check-ints-equal/disp32
+308     # . . discard args
+309     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+310     # check top
+311     58/pop-to-eax
+312     # . check-ints-equal(eax, 0, msg)
+313     # . . push args
+314     68/push  "F - test-pop: top"/imm32
+315     68/push  0/imm32
+316     50/push-eax
+317     # . . call
+318     e8/call  check-ints-equal/disp32
+319     # . . discard args
+320     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+321     # check size
+322     58/pop-to-eax
+323     # . check-ints-equal(eax, 8, msg)
+324     # . . push args
+325     68/push  "F - test-pop: size"/imm32
+326     68/push  8/imm32
+327     50/push-eax
+328     # . . call
+329     e8/call  check-ints-equal/disp32
+330     # . . discard args
+331     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+332     # . epilogue
+333     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+334     5d/pop-to-ebp
+335     c3/return
+336 
+337 # TODO: make this generic
+338 top:  # s: (addr stack) -> n/eax: int
+339     # . prologue
+340     55/push-ebp
+341     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+342     # . save registers
+343     51/push-ecx
+344     56/push-esi
+345     # esi = s
+346     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   8/disp8         .                 # copy *(ebp+8) to esi
+347     # if (s->top <= 0) abort
+348     81          7/subop/compare     0/mod/indirect  6/rm32/esi    .           .             .           .           .               0/imm32           # compare *esi
+349     7e/jump-if-<=  $top:abort/disp8
+350     # n = s->data[s->top - 4]
+351     8b/copy                         0/mod/indirect  6/rm32/esi    .           .             .           1/r32/ecx   .               .                 # copy *esi to ecx
+352     81          5/subop/subtract    3/mod/direct    1/rm32/ecx    .           .             .           .           .               4/imm32           # subtract from ecx
+353     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
+354 $top:end:
+355     # . restore registers
+356     5e/pop-to-esi
+357     59/pop-to-ecx
+358     # . epilogue
+359     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+360     5d/pop-to-ebp
+361     c3/return
+362 
+363 $top:abort:
+364     # print(stderr, "error: top: nothing left in stack")
+365     # . write-buffered(Stderr, "error: top: nothing left in stack")
+366     # . . push args
+367     68/push  "error: top: nothing left in stack"/imm32
+368     68/push  Stderr/imm32
+369     # . . call
+370     e8/call  write-buffered/disp32
+371     # . . discard args
+372     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+373     # . flush(Stderr)
+374     # . . push args
+375     68/push  Stderr/imm32
+376     # . . call
+377     e8/call  flush/disp32
+378     # . . discard args
+379     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+380     # . syscall(exit, 1)
+381     bb/copy-to-ebx  1/imm32
+382     e8/call  syscall_exit/disp32
+383     # never gets here
+384 
+385 test-top:
+386     # . prologue
+387     55/push-ebp
+388     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+389     # var stack/ecx = stack of size 8 containing just 0x42
+390     68/push  0/imm32
+391     68/push  0x42/imm32
+392     68/push  8/imm32/size
+393     68/push  4/imm32/top
+394     89/copy                         3/mod/direct    1/rm32/ecx    .           .             .           4/r32/esp   .               .                 # copy esp to ecx
+395     # eax = top(stack)
+396     # . . push args
+397     51/push-ecx
+398     # . . call
+399     e8/call  top/disp32
+400     # . . discard args
+401     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+402     # check-ints-equal(eax, 42, msg")
+403     # . . push args
+404     68/push  "F - test-top: result"/imm32
+405     68/push  0x42/imm32
+406     50/push-eax
+407     # . . call
+408     e8/call  check-ints-equal/disp32
+409     # . . discard args
+410     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+411     # . epilogue
+412     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+413     5d/pop-to-ebp
+414     c3/return
+415 
+416 # . . vim:nowrap:textwidth=0
+
+ + + -- cgit 1.4.1-2-gfad0