From 8fa32599bb288f9e51ebcf6f7c00339692c2a5b5 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Tue, 14 Jan 2020 01:24:54 -0800 Subject: 5889 --- html/092stack.subx.html | 477 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 477 insertions(+) create mode 100644 html/092stack.subx.html (limited to 'html/092stack.subx.html') diff --git a/html/092stack.subx.html b/html/092stack.subx.html new file mode 100644 index 00000000..1b0e6fe7 --- /dev/null +++ b/html/092stack.subx.html @@ -0,0 +1,477 @@ + + + + +Mu - 092stack.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/092stack.subx +
+  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-greater-or-equal-unsigned  $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-lesser-or-equal  $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-lesser-or-equal  $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-lesser-or-equal  $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
+
+ + + -- cgit 1.4.1-2-gfad0