From 5396e24cba8390ca2d70d99c7e8772eee4ec3a11 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Tue, 18 May 2021 13:01:59 -0700 Subject: . --- html/linux/stack_array.subx.html | 699 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 699 insertions(+) create mode 100644 html/linux/stack_array.subx.html (limited to 'html/linux/stack_array.subx.html') diff --git a/html/linux/stack_array.subx.html b/html/linux/stack_array.subx.html new file mode 100644 index 00000000..cbadf326 --- /dev/null +++ b/html/linux/stack_array.subx.html @@ -0,0 +1,699 @@ + + + + +Mu - linux/stack_array.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/main/linux/stack_array.subx +
+  1 == code
+  2 
+  3 # Problem: create a function which pushes n zeros on the stack.
+  4 # This is not a regular function, so it won't be idiomatic.
+  5 # Registers must be properly restored.
+  6 # Registers can be spilled, but that modifies the stack and needs to be
+  7 # cleaned up.
+  8 
+  9 # This file is kinda like a research notebook, to interactively arrive at the
+ 10 # solution. Nobody should have to do this without a computer. To run it:
+ 11 #   $ ./translate_subx_debug 000init.linux stack_array.subx  &&  bootstrap/bootstrap --debug --trace --dump run a.elf
+ 12 # There are multiple versions. You'll need to uncomment exactly one.
+ 13 
+ 14 # The final version has its own Entry, but the others share this one.
+ 15 #? Entry:
+ 16 #?     # . prologue
+ 17 #?     89/<- %ebp 4/r32/esp
+ 18 #?     #
+ 19 #?     68/push 0xfcfdfeff/imm32
+ 20 #?     b8/copy-to-eax 0x34353637/imm32
+ 21 #? $dump-stack:
+ 22 #?     (push-n-zero-bytes 0x20)
+ 23 #? $dump-stack2:
+ 24 #?     68/push 0x20202020/imm32
+ 25 #? $dump-stack3:
+ 26 #?     b8/copy-to-eax 1/imm32/exit
+ 27 #?     cd/syscall 0x80/imm8
+ 28 
+ 29 ## 0
+ 30 
+ 31 #? push-n-zero-bytes:  # n: int
+ 32 #?     # . prologue
+ 33 #?     55/push-ebp
+ 34 #?     89/<- %ebp 4/r32/esp
+ 35 #? $push-n-zero-bytes:end:
+ 36 #?     # . epilogue
+ 37 #?     89/<- %esp 5/r32/ebp
+ 38 #?     5d/pop-to-ebp
+ 39 #?     c3/return
+ 40 
+ 41 # stack at dump-stack:
+ 42 # 0 a: bdffffd0: 00000000     00000000     00000000      00000000
+ 43 # 0 a: bdffffe0: 00000000     00000000     00000000      00000000
+ 44 # 0 a: bdfffff0: 00000000     fcfdfeff     00000001      bf000000
+ 45 #
+ 46 # =>
+ 47 #
+ 48 # stack at dump-stack3:
+ 49 # 0 a: stack:
+ 50 # 0 a: bdffffd0: 00000000     00000000     00000000      00000000
+ 51 # 0 a: bdffffe0: 00000000     00000000     bdfffff8/ebp  090000cc/ra
+ 52 # 0 a: bdfffff0: 00000004/arg fcfdfeff     00000001      bf000000
+ 53 
+ 54 ## 1
+ 55 
+ 56 #? push-n-zero-bytes:  # n: int
+ 57 #?     # . prologue
+ 58 #?     55/push-ebp
+ 59 #?     89/<- %ebp 4/r32/esp
+ 60 #?     # . save registers
+ 61 #?     50/push-eax
+ 62 #? $push-n-zero-bytes:end:
+ 63 #?     # . restore registers
+ 64 #?     58/pop-to-eax
+ 65 #?     # . epilogue
+ 66 #?     5d/pop-to-ebp
+ 67 #?     c3/return
+ 68 
+ 69 # stack at dump-stack3:
+ 70 # 0 a: bdffffd0: 00000000 00000000 00000000 00000000
+ 71 # 0 a: bdffffe0: 00000000 34353637 bdfffff8 090000d1
+ 72 # 0 a: bdfffff0: 00000004 fcfdfeff 00000001 bf000000
+ 73 
+ 74 ## 2
+ 75 
+ 76 #? push-n-zero-bytes:  # n: int
+ 77 #?     # . prologue
+ 78 #?     55/push-ebp
+ 79 #?     89/<- %ebp 4/r32/esp
+ 80 #?     # . save registers
+ 81 #?     50/push-eax
+ 82 #?     #
+ 83 #?     8b/-> *(esp+8) 0/r32/eax
+ 84 #?     2b/subtract *(ebp+8) 4/r32/esp
+ 85 #?     89/<- *(esp+8) 0/r32/eax
+ 86 #? $push-n-zero-bytes:end:
+ 87 #?     # . restore registers
+ 88 #?     58/pop-to-eax
+ 89 #?     # . epilogue
+ 90 #?     5d/pop-to-ebp
+ 91 #?     c3/return
+ 92 
+ 93 # stack at dump-stack3:
+ 94 # 0 a: bdffff90: 00000000 00000000 00000000 00000000
+ 95 # 0 a: bdffffa0: 00000000 00000000 00000000 00000000
+ 96 # 0 a: bdffffb0: 00000000 00000000 00000000 00000000
+ 97 # 0 a: bdffffc0: 00000000 00000000 00000000 090000d1
+ 98 # 0 a: bdffffd0: 00000000 00000000 00000000 00000000
+ 99 # 0 a: bdffffe0: 00000000 34353637 bdfffff8 090000d1
+100 # 0 a: bdfffff0: 00000020 fcfdfeff 00000001 bf000000
+101 
+102 ## 3
+103 
+104 #? push-n-zero-bytes:  # n: int
+105 #?     # . prologue
+106 #?     55/push-ebp
+107 #?     89/<- %ebp 4/r32/esp
+108 #?     # . save registers
+109 #?     # -- esp = ebp
+110 #?     50/push-eax
+111 #?     # -- esp+8 = ebp+4
+112 #?     8b/-> *(esp+8) 0/r32/eax
+113 #?     2b/subtract *(ebp+8) 4/r32/esp
+114 #?     89/<- *(esp+8) 0/r32/eax
+115 #?     c7 0/subop/copy *(ebp+4) 0/imm32
+116 #? $push-n-zero-bytes:end:
+117 #?     # . restore registers
+118 #?     58/pop-to-eax
+119 #?     # . epilogue
+120 #?     5d/pop-to-ebp
+121 #?     c3/return
+122 
+123 # stack at dump-stack3:
+124 # 0 a: bdffff90: 00000000 00000000 00000000 00000000
+125 # 0 a: bdffffa0: 00000000 00000000 00000000 00000000
+126 # 0 a: bdffffb0: 00000000 00000000 00000000 00000000
+127 # 0 a: bdffffc0: 00000000 00000000 00000000 090000d1
+128 # 0 a: bdffffd0: 20202020 00000000 00000000 00000000
+129 # 0 a: bdffffe0: 00000000 34353637 bdfffff8 00000000
+130 # 0 a: bdfffff0: 00000020 fcfdfeff 00000001 bf000000
+131 
+132 ## 4
+133 
+134 #? push-n-zero-bytes:  # n: int
+135 #?     # . prologue
+136 #?     55/push-ebp
+137 #?     89/<- %ebp 4/r32/esp
+138 #?     # . save registers
+139 #?     # -- esp = ebp
+140 #?     50/push-eax
+141 #?     # copy return address over
+142 #?     # -- esp+8 = ebp+4
+143 #?     8b/-> *(esp+8) 0/r32/eax
+144 #?     2b/subtract *(ebp+8) 4/r32/esp
+145 #?     89/<- *(esp+8) 0/r32/eax
+146 #?     58/pop-to-eax
+147 #?     c7 0/subop/copy *(ebp+8) 0/imm32
+148 #?     c7 0/subop/copy *(ebp+4) 0/imm32
+149 #?     c7 0/subop/copy *(ebp+0) 0/imm32
+150 #?     c7 0/subop/copy *(ebp-4) 0/imm32
+151 #?     # . epilogue
+152 #?     5d/pop-to-ebp
+153 #?     c3/return
+154 
+155 # stack at dump-stack3:
+156 # 0 a: bdffff90: 00000000 00000000 00000000 00000000
+157 # 0 a: bdffffa0: 00000000 00000000 00000000 00000000
+158 # 0 a: bdffffb0: 00000000 00000000 00000000 00000000
+159 # 0 a: bdffffc0: 00000000 00000000 00000000 090000d1
+160 # 0 a: bdffffd0: 20202020 00000000 00000000 00000000
+161 # 0 a: bdffffe0: 00000000 00000000 00000000 00000000
+162 # 0 a: bdfffff0: 00000000 fcfdfeff 00000001 bf000000
+163 
+164 # Stack looks good now (the 20202020 marks where the array length 0x20 will
+165 # go, and the next 0x20 bytes show the space for the array has been zeroed
+166 # out).
+167 # Final issue: ebp has been clobbered on return.
+168 
+169 ## 5
+170 
+171 # I'd like to translate ebp to esp so we can stop pushing ebp. But we need to
+172 # hold 'n' somewhere, which would require a register, which we then need to
+173 # push.
+174 
+175 #? push-n-zero-bytes:  # n: int
+176 #?     55/push-ebp
+177 #?     89/<- %ebp 4/r32/esp
+178 #?     # -- esp = ebp
+179 #?     50/push-eax
+180 #? $push-n-zero-bytes:bulk-cleaning:
+181 #? $push-n-zero-bytes:copy-ra:
+182 #?     # -- esp+8 = ebp+4
+183 #?     8b/-> *(esp+8) 0/r32/eax
+184 #?     2b/subtract *(esp+0xc) 4/r32/esp
+185 #?     # -- esp+8+n = ebp+4
+186 #?     89/<- *(esp+8) 0/r32/eax
+187 #?     58/pop-to-eax
+188 #?     # -- esp+n = ebp
+189 #? $push-n-zero-bytes:spot-cleaning:
+190 #?     c7 0/subop/copy *(ebp+8) 0/imm32
+191 #?     c7 0/subop/copy *(ebp+4) 0/imm32
+192 #?     c7 0/subop/copy *(ebp+0) 0/imm32
+193 #?     c7 0/subop/copy *(ebp-4) 0/imm32
+194 #?     5d/pop-to-ebp
+195 #?     c3/return
+196 
+197 # stack at dump-stack3:
+198 # 0 a: bdffff90: 00000000 00000000 00000000 00000000
+199 # 0 a: bdffffa0: 00000000 00000000 00000000 00000000
+200 # 0 a: bdffffb0: 00000000 00000000 00000000 00000000
+201 # 0 a: bdffffc0: 00000000 00000000 00000000 090000d1
+202 # 0 a: bdffffd0: 20202020 00000000 00000000 00000000
+203 # 0 a: bdffffe0: 00000000 00000000 00000000 00000000
+204 # 0 a: bdfffff0: 00000000 fcfdfeff 00000001 bf000000
+205 
+206 # Bah. May be simpler to just create a new segment of global space for this
+207 # function.
+208 
+209 ## 6
+210 
+211 #? push-n-zero-bytes:  # n: int
+212 #?     89/<- *Push-n-zero-bytes-ebp 5/r32/ebp  # spill ebp without affecting stack
+213 #?     89/<- %ebp 4/r32/esp
+214 #?     # -- esp = ebp
+215 #?     50/push-eax
+216 #? $push-n-zero-bytes:bulk-cleaning:
+217 #? $push-n-zero-bytes:copy-ra:
+218 #?     # -- esp+8 = ebp+4
+219 #?     # -- esp+4 = ebp
+220 #?     8b/-> *(esp+4) 0/r32/eax
+221 #?     2b/subtract *(ebp+4) 4/r32/esp
+222 #?     # -- esp+4+n = ebp
+223 #?     89/<- *(esp+4) 0/r32/eax
+224 #?     58/pop-to-eax
+225 #?     # -- esp+n = ebp
+226 #? $push-n-zero-bytes:spot-cleaning:
+227 #?     c7 0/subop/copy *(ebp+4) 0/imm32
+228 #?     c7 0/subop/copy *(ebp+0) 0/imm32
+229 #?     c7 0/subop/copy *(ebp-4) 0/imm32
+230 #?     c7 0/subop/copy *(ebp-8) 0/imm32
+231 #?     8b/-> *Push-n-zero-bytes-ebp 5/r32/ebp  # restore spill
+232 #?     c3/return
+233 #? 
+234 #? == data
+235 #? Push-n-zero-bytes-ebp:  # (addr int)
+236 #?   0/imm32
+237 #? == code
+238 
+239 # stack at dump-stack3:
+240 # 0 a: bdffff90: 00000000 00000000 00000000 00000000
+241 # 0 a: bdffffa0: 00000000 00000000 00000000 00000000
+242 # 0 a: bdffffb0: 00000000 00000000 00000000 00000000
+243 # 0 a: bdffffc0: 00000000 00000000 00000000 090000d1
+244 # 0 a: bdffffd0: 20202020 00000000 00000000 00000000
+245 # 0 a: bdffffe0: 00000000 00000000 00000000 00000000
+246 # 0 a: bdfffff0: 00000000 fcfdfeff 00000001 bf000000
+247 
+248 # Ok, we're there. Now start using zero-out rather than spot-cleaning.
+249 
+250 ## 7: we need to zero out the return address, but we can't do it inside the function.
+251 ## So we'll change the signature slightly.
+252 ## Before: clear N bytes and then push N as the array length.
+253 ## After: clear N bytes, set *esp to N.
+254 ## The helper adds and clears N bytes *before* esp. esp can't be cleared since
+255 ## it contains the return address.
+256 
+257 #? Entry:
+258 #?     # . prologue
+259 #?     89/<- %ebp 4/r32/esp
+260 #?     #
+261 #?     68/push 0xfcfdfeff/imm32
+262 #?     b8/copy-to-eax 0x34353637/imm32
+263 #? $dump-stack0:
+264 #?     (push-n-zero-bytes 0x20)
+265 #? $dump-stack9:
+266 #?     c7 0/subop/copy *esp 0x20/imm32
+267 #? $dump-stacka:
+268 #?     b8/copy-to-eax 1/imm32/exit
+269 #?     cd/syscall 0x80/imm8
+270 #? 
+271 #? push-n-zero-bytes:  # n: int
+272 #? $push-n-zero-bytes:prologue:
+273 #?     89/<- *Push-n-zero-bytes-ebp 5/r32/ebp  # spill ebp without affecting stack
+274 #?     89/<- %ebp 4/r32/esp
+275 #? $push-n-zero-bytes:copy-ra:
+276 #? $dump-stack1:
+277 #?     # -- esp = ebp
+278 #?     50/push-eax
+279 #? $dump-stack2:
+280 #?     # -- esp+8 = ebp+4
+281 #?     # -- esp+4 = ebp
+282 #?     8b/-> *(esp+4) 0/r32/eax
+283 #? $dump-stack3:
+284 #?     2b/subtract *(ebp+4) 4/r32/esp
+285 #? $dump-stack4:
+286 #?     # -- esp+4+n = ebp
+287 #?     89/<- *(esp+4) 0/r32/eax
+288 #? $dump-stack5:
+289 #?     58/pop-to-eax
+290 #?     # -- esp+n = ebp
+291 #? $push-n-zero-bytes:bulk-cleaning:
+292 #? $dump-stack6:
+293 #?     89/<- *Push-n-zero-bytes-esp 4/r32/esp
+294 #?     81 0/subop/add *Push-n-zero-bytes-esp 4/imm32
+295 #? $dump-stack7:
+296 #?     (zero-out *Push-n-zero-bytes-esp *(ebp+4))  # n
+297 #? $push-n-zero-bytes:epilogue:
+298 #? $dump-stack8:
+299 #?     8b/-> *Push-n-zero-bytes-ebp 5/r32/ebp  # restore spill
+300 #?     c3/return
+301 #? 
+302 #? zero-out:  # start: (addr byte), len: int
+303 #?     # pseudocode:
+304 #?     #   curr/esi = start
+305 #?     #   i/ecx = 0
+306 #?     #   while true
+307 #?     #     if (i >= len) break
+308 #?     #     *curr = 0
+309 #?     #     ++curr
+310 #?     #     ++i
+311 #?     #
+312 #?     # . prologue
+313 #?     55/push-ebp
+314 #?     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+315 #?     # . save registers
+316 #?     50/push-eax
+317 #?     51/push-ecx
+318 #?     52/push-edx
+319 #?     56/push-esi
+320 #?     # curr/esi = start
+321 #?     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   8/disp8         .                 # copy *(ebp+8) to esi
+322 #?     # var i/ecx: int = 0
+323 #?     31/xor                          3/mod/direct    1/rm32/ecx    .           .             .           1/r32/ecx   .               .                 # clear ecx
+324 #?     # edx = len
+325 #?     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           2/r32/edx   0xc/disp8       .                 # copy *(ebp+12) to edx
+326 #? $zero-out:loop:
+327 #?     # if (i >= len) break
+328 #?     39/compare                      3/mod/direct    1/rm32/ecx    .           .             .           2/r32/edx   .               .                 # compare ecx with edx
+329 #?     7d/jump-if->=  $zero-out:end/disp8
+330 #?     # *curr = 0
+331 #?     c6          0/subop/copy        0/mod/direct    6/rm32/esi    .           .             .           .           .               0/imm8            # copy byte to *esi
+332 #?     # ++curr
+333 #?     46/increment-esi
+334 #?     # ++i
+335 #?     41/increment-ecx
+336 #?     eb/jump  $zero-out:loop/disp8
+337 #? $zero-out:end:
+338 #?     # . restore registers
+339 #?     5e/pop-to-esi
+340 #?     5a/pop-to-edx
+341 #?     59/pop-to-ecx
+342 #?     58/pop-to-eax
+343 #?     # . epilogue
+344 #?     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+345 #?     5d/pop-to-ebp
+346 #?     c3/return
+347 #? 
+348 #? == data
+349 #? Push-n-zero-bytes-ebp:  # (addr int)
+350 #?   0/imm32
+351 #? Push-n-zero-bytes-esp:  # (addr int)
+352 #?   0/imm32
+353 #? == code
+354 
+355 # stack at dump-stack0:
+356 # 0 a: bdffffb0:  00000000   00000000   00000000   00000000 
+357 # 0 a: bdffffc0:  00000000   00000000   00000000   00000000 
+358 # 0 a: bdffffd0:  00000000   00000000   00000000   00000000 
+359 # 0 a: bdffffe0:  00000000   00000000   00000000   00000000 
+360 # 0 a: bdfffff0:  00000000  [fcfdfeff]  00000001   bf000000 
+361 
+362 # desired state after push-n-zero-bytes:
+363 # 0 a: bdffff90:  00000000   00000000   00000000   00000000 
+364 # 0 a: bdffffa0:  00000000   00000000   00000000   00000000 
+365 # 0 a: bdffffb0:  00000000   00000000   00000000   bdffffec 
+366 # 0 a: bdffffc0:  0900012a   bdffffd0   00000020   090000d1 
+367 # 0 a: bdffffd0: [rrrrrrrr]  00000000   00000000   00000000 
+368 # 0 a: bdffffe0:  00000000   00000000   00000000   00000000 
+369 # 0 a: bdfffff0:  00000000   fcfdfeff   00000001   bf000000 
+370 
+371 # Stack pointer contains ra is caller's responsibility to over-write with array length.
+372 
+373 # actual state:
+374 # 0 a: bdffff90:  00000000   00000000   00000000   00000000
+375 # 0 a: bdffffa0:  00000000   00000000   00000000   00000000
+376 # 0 a: bdffffb0:  00000000   00000000   00000000   bdffffec
+377 # 0 a: bdffffc0:  0900012a   bdffffd0   00000020   090000d1
+378 # 0 a: bdffffd0:  00000000  [00000000]  00000000   00000000
+379 # 0 a: bdffffe0:  00000000   00000000   00000000   00000000
+380 # 0 a: bdfffff0:  00000020   fcfdfeff   00000001   bf000000
+381 
+382 # Couple of issues. But where does the return address disappear to?
+383 
+384 ## 8:
+385 
+386 #? Entry:
+387 #?     # . prologue
+388 #?     89/<- %ebp 4/r32/esp
+389 #?     #
+390 #?     68/push 0xfcfdfeff/imm32
+391 #?     b8/copy-to-eax 0x34353637/imm32
+392 #? $dump-stack0:
+393 #?     (push-n-zero-bytes 0x20)
+394 #? $dump-stack9:
+395 #?     68/push 0x20/imm32
+396 #? #?     c7 0/subop/copy *esp 0x20/imm32
+397 #? $dump-stacka:
+398 #?     b8/copy-to-eax 1/imm32/exit
+399 #?     cd/syscall 0x80/imm8
+400 #? 
+401 #? push-n-zero-bytes:  # n: int
+402 #? $push-n-zero-bytes:prologue:
+403 #?     89/<- *Push-n-zero-bytes-ebp 5/r32/ebp  # spill ebp without affecting stack
+404 #?     89/<- %ebp 4/r32/esp
+405 #? $push-n-zero-bytes:copy-ra:
+406 #? $dump-stack1:
+407 #?     # -- esp = ebp
+408 #?     50/push-eax
+409 #? $dump-stack2:
+410 #?     # -- esp+8 = ebp+4
+411 #?     # -- esp+4 = ebp
+412 #?     8b/-> *(esp+4) 0/r32/eax
+413 #? $dump-stack3:
+414 #?     2b/subtract *(ebp+4) 4/r32/esp
+415 #? $dump-stack4:
+416 #?     # -- esp+4+n = ebp
+417 #?     89/<- *(esp+4) 0/r32/eax
+418 #? $dump-stack5:
+419 #?     58/pop-to-eax
+420 #?     # -- esp+n = ebp
+421 #? $push-n-zero-bytes:bulk-cleaning:
+422 #? $dump-stack6:
+423 #?     89/<- *Push-n-zero-bytes-esp 4/r32/esp
+424 #?     81 0/subop/add *Push-n-zero-bytes-esp 4/imm32
+425 #? $dump-stack7:
+426 #?     (zero-out *Push-n-zero-bytes-esp *(ebp+4))  # n
+427 #? $push-n-zero-bytes:epilogue:
+428 #? $dump-stack8:
+429 #?     8b/-> *Push-n-zero-bytes-ebp 5/r32/ebp  # restore spill
+430 #?     c3/return
+431 #? 
+432 #? zero-out:  # start: (addr byte), len: int
+433 #?     # pseudocode:
+434 #?     #   curr/esi = start
+435 #?     #   i/ecx = 0
+436 #?     #   while true
+437 #?     #     if (i >= len) break
+438 #?     #     *curr = 0
+439 #?     #     ++curr
+440 #?     #     ++i
+441 #?     #
+442 #?     # . prologue
+443 #?     55/push-ebp
+444 #?     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+445 #?     # . save registers
+446 #?     50/push-eax
+447 #?     51/push-ecx
+448 #?     52/push-edx
+449 #?     56/push-esi
+450 #?     # curr/esi = start
+451 #?     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   8/disp8         .                 # copy *(ebp+8) to esi
+452 #?     # var i/ecx: int = 0
+453 #?     31/xor                          3/mod/direct    1/rm32/ecx    .           .             .           1/r32/ecx   .               .                 # clear ecx
+454 #?     # edx = len
+455 #?     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           2/r32/edx   0xc/disp8       .                 # copy *(ebp+12) to edx
+456 #? $zero-out:loop:
+457 #?     # if (i >= len) break
+458 #?     39/compare                      3/mod/direct    1/rm32/ecx    .           .             .           2/r32/edx   .               .                 # compare ecx with edx
+459 #?     7d/jump-if->=  $zero-out:end/disp8
+460 #?     # *curr = 0
+461 #?     c6          0/subop/copy        0/mod/direct    6/rm32/esi    .           .             .           .           .               0/imm8            # copy byte to *esi
+462 #?     # ++curr
+463 #?     46/increment-esi
+464 #?     # ++i
+465 #?     41/increment-ecx
+466 #?     eb/jump  $zero-out:loop/disp8
+467 #? $zero-out:end:
+468 #?     # . restore registers
+469 #?     5e/pop-to-esi
+470 #?     5a/pop-to-edx
+471 #?     59/pop-to-ecx
+472 #?     58/pop-to-eax
+473 #?     # . epilogue
+474 #?     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+475 #?     5d/pop-to-ebp
+476 #?     c3/return
+477 #? 
+478 #? == data
+479 #? Push-n-zero-bytes-ebp:  # (addr int)
+480 #?   0/imm32
+481 #? Push-n-zero-bytes-esp:  # (addr int)
+482 #?   0/imm32
+483 #? == code
+484 
+485 # stack at dump-stack0:
+486 # 0 a: bdffffb0:  00000000   00000000   00000000   00000000 
+487 # 0 a: bdffffc0:  00000000   00000000   00000000   00000000 
+488 # 0 a: bdffffd0:  00000000   00000000   00000000   00000000 
+489 # 0 a: bdffffe0:  00000000   00000000   00000000   00000000 
+490 # 0 a: bdfffff0:  00000000  [fcfdfeff]  00000001   bf000000 
+491 
+492 # desired state after push-n-zero-bytes:
+493 # 0 a: bdffff90:  00000000   00000000   00000000   00000000 
+494 # 0 a: bdffffa0:  00000000   00000000   00000000   00000000 
+495 # 0 a: bdffffb0:  00000000   00000000   00000000   bdffffec 
+496 # 0 a: bdffffc0:  0900012a   bdffffd0   00000020   090000d1 
+497 # 0 a: bdffffd0: [rrrrrrrr]  00000000   00000000   00000000 
+498 # 0 a: bdffffe0:  00000000   00000000   00000000   00000000 
+499 # 0 a: bdfffff0:  00000000   fcfdfeff   00000001   bf000000 
+500 
+501 # actual state:
+502 # 0 a: bdffff90:  00000000   00000000   00000000   00000000
+503 # 0 a: bdffffa0:  00000000   00000000   00000000   00000000
+504 # 0 a: bdffffb0:  00000000   00000000   00000000   bdffffec
+505 # 0 a: bdffffc0:  09000124   bdffffd0   00000020   090000d1
+506 # 0 a: bdffffd0: [00000000]  00000000   00000000   00000000
+507 # 0 a: bdffffe0:  00000000   00000000   00000000   00000000
+508 # 0 a: bdfffff0:  00000020   fcfdfeff   00000001   bf000000
+509 
+510 # Ok, just one diff, at bdfffff0
+511 
+512 ## 9:
+513 
+514 Entry:
+515     # . prologue
+516     89/<- %ebp 4/r32/esp
+517     #
+518     68/push 0xfcfdfeff/imm32
+519     b8/copy-to-eax 0x34353637/imm32
+520 $dump-stack0:
+521     (push-n-zero-bytes 0x20)
+522 $dump-stack9:
+523     68/push 0x20/imm32
+524 $dump-stacka:
+525     b8/copy-to-eax 1/imm32/exit
+526     cd/syscall 0x80/imm8
+527 
+528 push-n-zero-bytes:  # n: int
+529 $push-n-zero-bytes:prologue:
+530     89/<- *Push-n-zero-bytes-ebp 5/r32/ebp  # spill ebp without affecting stack
+531     89/<- %ebp 4/r32/esp
+532 $push-n-zero-bytes:copy-ra:
+533 $dump-stack1:
+534     # -- esp = ebp
+535     50/push-eax
+536 $dump-stack2:
+537     # -- esp+8 = ebp+4
+538     # -- esp+4 = ebp
+539     8b/-> *(esp+4) 0/r32/eax
+540 $dump-stack3:
+541     2b/subtract *(ebp+4) 4/r32/esp
+542 $dump-stack4:
+543     # -- esp+4+n = ebp
+544     89/<- *(esp+4) 0/r32/eax
+545 $dump-stack5:
+546     58/pop-to-eax
+547     # -- esp+n = ebp
+548 $push-n-zero-bytes:bulk-cleaning:
+549 $dump-stack6:
+550     89/<- *Push-n-zero-bytes-esp 4/r32/esp
+551     81 0/subop/add *Push-n-zero-bytes-esp 4/imm32
+552 $dump-stack7:
+553     81 0/subop/add *(ebp+4) 4/imm32
+554     (zero-out *Push-n-zero-bytes-esp *(ebp+4))  # n
+555 $push-n-zero-bytes:epilogue:
+556 $dump-stack8:
+557     8b/-> *Push-n-zero-bytes-ebp 5/r32/ebp  # restore spill
+558     c3/return
+559 
+560 zero-out:  # start: (addr byte), len: int
+561     # pseudocode:
+562     #   curr/esi = start
+563     #   i/ecx = 0
+564     #   while true
+565     #     if (i >= len) break
+566     #     *curr = 0
+567     #     ++curr
+568     #     ++i
+569     #
+570     # . prologue
+571     55/push-ebp
+572     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+573     # . save registers
+574     50/push-eax
+575     51/push-ecx
+576     52/push-edx
+577     56/push-esi
+578     # curr/esi = start
+579     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   8/disp8         .                 # copy *(ebp+8) to esi
+580     # var i/ecx: int = 0
+581     31/xor                          3/mod/direct    1/rm32/ecx    .           .             .           1/r32/ecx   .               .                 # clear ecx
+582     # edx = len
+583     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           2/r32/edx   0xc/disp8       .                 # copy *(ebp+12) to edx
+584 $zero-out:loop:
+585     # if (i >= len) break
+586     39/compare                      3/mod/direct    1/rm32/ecx    .           .             .           2/r32/edx   .               .                 # compare ecx with edx
+587     7d/jump-if->=  $zero-out:end/disp8
+588     # *curr = 0
+589     c6          0/subop/copy        0/mod/direct    6/rm32/esi    .           .             .           .           .               0/imm8            # copy byte to *esi
+590     # ++curr
+591     46/increment-esi
+592     # ++i
+593     41/increment-ecx
+594     eb/jump  $zero-out:loop/disp8
+595 $zero-out:end:
+596     # . restore registers
+597     5e/pop-to-esi
+598     5a/pop-to-edx
+599     59/pop-to-ecx
+600     58/pop-to-eax
+601     # . epilogue
+602     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+603     5d/pop-to-ebp
+604     c3/return
+605 
+606 == data
+607 Push-n-zero-bytes-ebp:  # (addr int)
+608   0/imm32
+609 Push-n-zero-bytes-esp:  # (addr int)
+610   0/imm32
+611 == code
+612 
+613 # stack at dump-stack0:
+614 # 0 a: bdffffb0:  00000000   00000000   00000000   00000000 
+615 # 0 a: bdffffc0:  00000000   00000000   00000000   00000000 
+616 # 0 a: bdffffd0:  00000000   00000000   00000000   00000000 
+617 # 0 a: bdffffe0:  00000000   00000000   00000000   00000000 
+618 # 0 a: bdfffff0:  00000000  [fcfdfeff]  00000001   bf000000 
+619 
+620 # desired state after push-n-zero-bytes:
+621 # 0 a: bdffff90:  00000000   00000000   00000000   00000000 
+622 # 0 a: bdffffa0:  00000000   00000000   00000000   00000000 
+623 # 0 a: bdffffb0:  00000000   00000000   00000000   bdffffec 
+624 # 0 a: bdffffc0:  0900012a   bdffffd0   00000020   090000d1 
+625 # 0 a: bdffffd0: [xxxxxxxx]  00000000   00000000   00000000 
+626 # 0 a: bdffffe0:  00000000   00000000   00000000   00000000 
+627 # 0 a: bdfffff0:  00000000   fcfdfeff   00000001   bf000000 
+628 
+629 # actual state:
+630 # 0 a: bdffff90:  00000000   00000000   00000000   00000000
+631 # 0 a: bdffffa0:  00000000   00000000   00000000   00000000
+632 # 0 a: bdffffb0:  00000000   00000000   00000000   bdffffec
+633 # 0 a: bdffffc0:  0900012f   bdffffd0   00000024   090000d1
+634 # 0 a: bdffffd0: [00000000]  00000000   00000000   00000000
+635 # 0 a: bdffffe0:  00000000   00000000   00000000   00000000
+636 # 0 a: bdfffff0:  00000000   fcfdfeff   00000001   bf000000
+
+ + + -- cgit 1.4.1-2-gfad0