about summary refs log tree commit diff stats
path: root/tools
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2021-03-24 09:12:32 -0700
committerKartik Agaram <vc@akkartik.com>2021-03-24 09:12:32 -0700
commitc2aeba0a110eb57fe41ab3388970e55274e15e14 (patch)
treed867babbd613aaace0825c76c5c13bde1698aef3 /tools
parent754d813bc5044fb7a9ce586692b627512ca84fb5 (diff)
downloadmu-c2aeba0a110eb57fe41ab3388970e55274e15e14.tar.gz
.
Diffstat (limited to 'tools')
-rw-r--r--tools/stack_array.subx636
1 files changed, 0 insertions, 636 deletions
diff --git a/tools/stack_array.subx b/tools/stack_array.subx
deleted file mode 100644
index 5affbc56..00000000
--- a/tools/stack_array.subx
+++ /dev/null
@@ -1,636 +0,0 @@
-== code
-
-# Problem: create a function which pushes n zeros on the stack.
-# This is not a regular function, so it won't be idiomatic.
-# Registers must be properly restored.
-# Registers can be spilled, but that modifies the stack and needs to be
-# cleaned up.
-
-# This file is kinda like a research notebook, to interactively arrive at the
-# solution. Nobody should have to do this without a computer. To run it:
-#   $ ./translate_subx_debug init.linux tools/stack_array.subx  &&  bootstrap --debug --trace --dump run a.elf
-# There are multiple versions. You'll need to uncomment exactly one.
-
-# The final version has its own Entry, but the others share this one.
-#? Entry:
-#?     # . prologue
-#?     89/<- %ebp 4/r32/esp
-#?     #
-#?     68/push 0xfcfdfeff/imm32
-#?     b8/copy-to-eax 0x34353637/imm32
-#? $dump-stack:
-#?     (push-n-zero-bytes 0x20)
-#? $dump-stack2:
-#?     68/push 0x20202020/imm32
-#? $dump-stack3:
-#?     b8/copy-to-eax 1/imm32/exit
-#?     cd/syscall 0x80/imm8
-
-## 0
-
-#? push-n-zero-bytes:  # n: int
-#?     # . prologue
-#?     55/push-ebp
-#?     89/<- %ebp 4/r32/esp
-#? $push-n-zero-bytes:end:
-#?     # . epilogue
-#?     89/<- %esp 5/r32/ebp
-#?     5d/pop-to-ebp
-#?     c3/return
-
-# stack at dump-stack:
-# 0 a: bdffffd0: 00000000     00000000     00000000      00000000
-# 0 a: bdffffe0: 00000000     00000000     00000000      00000000
-# 0 a: bdfffff0: 00000000     fcfdfeff     00000001      bf000000
-#
-# =>
-#
-# stack at dump-stack3:
-# 0 a: stack:
-# 0 a: bdffffd0: 00000000     00000000     00000000      00000000
-# 0 a: bdffffe0: 00000000     00000000     bdfffff8/ebp  090000cc/ra
-# 0 a: bdfffff0: 00000004/arg fcfdfeff     00000001      bf000000
-
-## 1
-
-#? push-n-zero-bytes:  # n: int
-#?     # . prologue
-#?     55/push-ebp
-#?     89/<- %ebp 4/r32/esp
-#?     # . save registers
-#?     50/push-eax
-#? $push-n-zero-bytes:end:
-#?     # . restore registers
-#?     58/pop-to-eax
-#?     # . epilogue
-#?     5d/pop-to-ebp
-#?     c3/return
-
-# stack at dump-stack3:
-# 0 a: bdffffd0: 00000000 00000000 00000000 00000000
-# 0 a: bdffffe0: 00000000 34353637 bdfffff8 090000d1
-# 0 a: bdfffff0: 00000004 fcfdfeff 00000001 bf000000
-
-## 2
-
-#? push-n-zero-bytes:  # n: int
-#?     # . prologue
-#?     55/push-ebp
-#?     89/<- %ebp 4/r32/esp
-#?     # . save registers
-#?     50/push-eax
-#?     #
-#?     8b/-> *(esp+8) 0/r32/eax
-#?     2b/subtract *(ebp+8) 4/r32/esp
-#?     89/<- *(esp+8) 0/r32/eax
-#? $push-n-zero-bytes:end:
-#?     # . restore registers
-#?     58/pop-to-eax
-#?     # . epilogue
-#?     5d/pop-to-ebp
-#?     c3/return
-
-# stack at dump-stack3:
-# 0 a: bdffff90: 00000000 00000000 00000000 00000000
-# 0 a: bdffffa0: 00000000 00000000 00000000 00000000
-# 0 a: bdffffb0: 00000000 00000000 00000000 00000000
-# 0 a: bdffffc0: 00000000 00000000 00000000 090000d1
-# 0 a: bdffffd0: 00000000 00000000 00000000 00000000
-# 0 a: bdffffe0: 00000000 34353637 bdfffff8 090000d1
-# 0 a: bdfffff0: 00000020 fcfdfeff 00000001 bf000000
-
-## 3
-
-#? push-n-zero-bytes:  # n: int
-#?     # . prologue
-#?     55/push-ebp
-#?     89/<- %ebp 4/r32/esp
-#?     # . save registers
-#?     # -- esp = ebp
-#?     50/push-eax
-#?     # -- esp+8 = ebp+4
-#?     8b/-> *(esp+8) 0/r32/eax
-#?     2b/subtract *(ebp+8) 4/r32/esp
-#?     89/<- *(esp+8) 0/r32/eax
-#?     c7 0/subop/copy *(ebp+4) 0/imm32
-#? $push-n-zero-bytes:end:
-#?     # . restore registers
-#?     58/pop-to-eax
-#?     # . epilogue
-#?     5d/pop-to-ebp
-#?     c3/return
-
-# stack at dump-stack3:
-# 0 a: bdffff90: 00000000 00000000 00000000 00000000
-# 0 a: bdffffa0: 00000000 00000000 00000000 00000000
-# 0 a: bdffffb0: 00000000 00000000 00000000 00000000
-# 0 a: bdffffc0: 00000000 00000000 00000000 090000d1
-# 0 a: bdffffd0: 20202020 00000000 00000000 00000000
-# 0 a: bdffffe0: 00000000 34353637 bdfffff8 00000000
-# 0 a: bdfffff0: 00000020 fcfdfeff 00000001 bf000000
-
-## 4
-
-#? push-n-zero-bytes:  # n: int
-#?     # . prologue
-#?     55/push-ebp
-#?     89/<- %ebp 4/r32/esp
-#?     # . save registers
-#?     # -- esp = ebp
-#?     50/push-eax
-#?     # copy return address over
-#?     # -- esp+8 = ebp+4
-#?     8b/-> *(esp+8) 0/r32/eax
-#?     2b/subtract *(ebp+8) 4/r32/esp
-#?     89/<- *(esp+8) 0/r32/eax
-#?     58/pop-to-eax
-#?     c7 0/subop/copy *(ebp+8) 0/imm32
-#?     c7 0/subop/copy *(ebp+4) 0/imm32
-#?     c7 0/subop/copy *(ebp+0) 0/imm32
-#?     c7 0/subop/copy *(ebp-4) 0/imm32
-#?     # . epilogue
-#?     5d/pop-to-ebp
-#?     c3/return
-
-# stack at dump-stack3:
-# 0 a: bdffff90: 00000000 00000000 00000000 00000000
-# 0 a: bdffffa0: 00000000 00000000 00000000 00000000
-# 0 a: bdffffb0: 00000000 00000000 00000000 00000000
-# 0 a: bdffffc0: 00000000 00000000 00000000 090000d1
-# 0 a: bdffffd0: 20202020 00000000 00000000 00000000
-# 0 a: bdffffe0: 00000000 00000000 00000000 00000000
-# 0 a: bdfffff0: 00000000 fcfdfeff 00000001 bf000000
-
-# Stack looks good now (the 20202020 marks where the array length 0x20 will
-# go, and the next 0x20 bytes show the space for the array has been zeroed
-# out).
-# Final issue: ebp has been clobbered on return.
-
-## 5
-
-# I'd like to translate ebp to esp so we can stop pushing ebp. But we need to
-# hold 'n' somewhere, which would require a register, which we then need to
-# push.
-
-#? push-n-zero-bytes:  # n: int
-#?     55/push-ebp
-#?     89/<- %ebp 4/r32/esp
-#?     # -- esp = ebp
-#?     50/push-eax
-#? $push-n-zero-bytes:bulk-cleaning:
-#? $push-n-zero-bytes:copy-ra:
-#?     # -- esp+8 = ebp+4
-#?     8b/-> *(esp+8) 0/r32/eax
-#?     2b/subtract *(esp+0xc) 4/r32/esp
-#?     # -- esp+8+n = ebp+4
-#?     89/<- *(esp+8) 0/r32/eax
-#?     58/pop-to-eax
-#?     # -- esp+n = ebp
-#? $push-n-zero-bytes:spot-cleaning:
-#?     c7 0/subop/copy *(ebp+8) 0/imm32
-#?     c7 0/subop/copy *(ebp+4) 0/imm32
-#?     c7 0/subop/copy *(ebp+0) 0/imm32
-#?     c7 0/subop/copy *(ebp-4) 0/imm32
-#?     5d/pop-to-ebp
-#?     c3/return
-
-# stack at dump-stack3:
-# 0 a: bdffff90: 00000000 00000000 00000000 00000000
-# 0 a: bdffffa0: 00000000 00000000 00000000 00000000
-# 0 a: bdffffb0: 00000000 00000000 00000000 00000000
-# 0 a: bdffffc0: 00000000 00000000 00000000 090000d1
-# 0 a: bdffffd0: 20202020 00000000 00000000 00000000
-# 0 a: bdffffe0: 00000000 00000000 00000000 00000000
-# 0 a: bdfffff0: 00000000 fcfdfeff 00000001 bf000000
-
-# Bah. May be simpler to just create a new segment of global space for this
-# function.
-
-## 6
-
-#? push-n-zero-bytes:  # n: int
-#?     89/<- *Push-n-zero-bytes-ebp 5/r32/ebp  # spill ebp without affecting stack
-#?     89/<- %ebp 4/r32/esp
-#?     # -- esp = ebp
-#?     50/push-eax
-#? $push-n-zero-bytes:bulk-cleaning:
-#? $push-n-zero-bytes:copy-ra:
-#?     # -- esp+8 = ebp+4
-#?     # -- esp+4 = ebp
-#?     8b/-> *(esp+4) 0/r32/eax
-#?     2b/subtract *(ebp+4) 4/r32/esp
-#?     # -- esp+4+n = ebp
-#?     89/<- *(esp+4) 0/r32/eax
-#?     58/pop-to-eax
-#?     # -- esp+n = ebp
-#? $push-n-zero-bytes:spot-cleaning:
-#?     c7 0/subop/copy *(ebp+4) 0/imm32
-#?     c7 0/subop/copy *(ebp+0) 0/imm32
-#?     c7 0/subop/copy *(ebp-4) 0/imm32
-#?     c7 0/subop/copy *(ebp-8) 0/imm32
-#?     8b/-> *Push-n-zero-bytes-ebp 5/r32/ebp  # restore spill
-#?     c3/return
-#? 
-#? == data
-#? Push-n-zero-bytes-ebp:  # (addr int)
-#?   0/imm32
-#? == code
-
-# stack at dump-stack3:
-# 0 a: bdffff90: 00000000 00000000 00000000 00000000
-# 0 a: bdffffa0: 00000000 00000000 00000000 00000000
-# 0 a: bdffffb0: 00000000 00000000 00000000 00000000
-# 0 a: bdffffc0: 00000000 00000000 00000000 090000d1
-# 0 a: bdffffd0: 20202020 00000000 00000000 00000000
-# 0 a: bdffffe0: 00000000 00000000 00000000 00000000
-# 0 a: bdfffff0: 00000000 fcfdfeff 00000001 bf000000
-
-# Ok, we're there. Now start using zero-out rather than spot-cleaning.
-
-## 7: we need to zero out the return address, but we can't do it inside the function.
-## So we'll change the signature slightly.
-## Before: clear N bytes and then push N as the array length.
-## After: clear N bytes, set *esp to N.
-## The helper adds and clears N bytes *before* esp. esp can't be cleared since
-## it contains the return address.
-
-#? Entry:
-#?     # . prologue
-#?     89/<- %ebp 4/r32/esp
-#?     #
-#?     68/push 0xfcfdfeff/imm32
-#?     b8/copy-to-eax 0x34353637/imm32
-#? $dump-stack0:
-#?     (push-n-zero-bytes 0x20)
-#? $dump-stack9:
-#?     c7 0/subop/copy *esp 0x20/imm32
-#? $dump-stacka:
-#?     b8/copy-to-eax 1/imm32/exit
-#?     cd/syscall 0x80/imm8
-#? 
-#? push-n-zero-bytes:  # n: int
-#? $push-n-zero-bytes:prologue:
-#?     89/<- *Push-n-zero-bytes-ebp 5/r32/ebp  # spill ebp without affecting stack
-#?     89/<- %ebp 4/r32/esp
-#? $push-n-zero-bytes:copy-ra:
-#? $dump-stack1:
-#?     # -- esp = ebp
-#?     50/push-eax
-#? $dump-stack2:
-#?     # -- esp+8 = ebp+4
-#?     # -- esp+4 = ebp
-#?     8b/-> *(esp+4) 0/r32/eax
-#? $dump-stack3:
-#?     2b/subtract *(ebp+4) 4/r32/esp
-#? $dump-stack4:
-#?     # -- esp+4+n = ebp
-#?     89/<- *(esp+4) 0/r32/eax
-#? $dump-stack5:
-#?     58/pop-to-eax
-#?     # -- esp+n = ebp
-#? $push-n-zero-bytes:bulk-cleaning:
-#? $dump-stack6:
-#?     89/<- *Push-n-zero-bytes-esp 4/r32/esp
-#?     81 0/subop/add *Push-n-zero-bytes-esp 4/imm32
-#? $dump-stack7:
-#?     (zero-out *Push-n-zero-bytes-esp *(ebp+4))  # n
-#? $push-n-zero-bytes:epilogue:
-#? $dump-stack8:
-#?     8b/-> *Push-n-zero-bytes-ebp 5/r32/ebp  # restore spill
-#?     c3/return
-#? 
-#? zero-out:  # start: (addr byte), len: int
-#?     # pseudocode:
-#?     #   curr/esi = start
-#?     #   i/ecx = 0
-#?     #   while true
-#?     #     if (i >= len) break
-#?     #     *curr = 0
-#?     #     ++curr
-#?     #     ++i
-#?     #
-#?     # . prologue
-#?     55/push-ebp
-#?     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
-#?     # . save registers
-#?     50/push-eax
-#?     51/push-ecx
-#?     52/push-edx
-#?     56/push-esi
-#?     # curr/esi = start
-#?     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   8/disp8         .                 # copy *(ebp+8) to esi
-#?     # var i/ecx: int = 0
-#?     31/xor                          3/mod/direct    1/rm32/ecx    .           .             .           1/r32/ecx   .               .                 # clear ecx
-#?     # edx = len
-#?     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           2/r32/edx   0xc/disp8       .                 # copy *(ebp+12) to edx
-#? $zero-out:loop:
-#?     # if (i >= len) break
-#?     39/compare                      3/mod/direct    1/rm32/ecx    .           .             .           2/r32/edx   .               .                 # compare ecx with edx
-#?     7d/jump-if->=  $zero-out:end/disp8
-#?     # *curr = 0
-#?     c6          0/subop/copy        0/mod/direct    6/rm32/esi    .           .             .           .           .               0/imm8            # copy byte to *esi
-#?     # ++curr
-#?     46/increment-esi
-#?     # ++i
-#?     41/increment-ecx
-#?     eb/jump  $zero-out:loop/disp8
-#? $zero-out:end:
-#?     # . restore registers
-#?     5e/pop-to-esi
-#?     5a/pop-to-edx
-#?     59/pop-to-ecx
-#?     58/pop-to-eax
-#?     # . epilogue
-#?     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
-#?     5d/pop-to-ebp
-#?     c3/return
-#? 
-#? == data
-#? Push-n-zero-bytes-ebp:  # (addr int)
-#?   0/imm32
-#? Push-n-zero-bytes-esp:  # (addr int)
-#?   0/imm32
-#? == code
-
-# stack at dump-stack0:
-# 0 a: bdffffb0:  00000000   00000000   00000000   00000000 
-# 0 a: bdffffc0:  00000000   00000000   00000000   00000000 
-# 0 a: bdffffd0:  00000000   00000000   00000000   00000000 
-# 0 a: bdffffe0:  00000000   00000000   00000000   00000000 
-# 0 a: bdfffff0:  00000000  [fcfdfeff]  00000001   bf000000 
-
-# desired state after push-n-zero-bytes:
-# 0 a: bdffff90:  00000000   00000000   00000000   00000000 
-# 0 a: bdffffa0:  00000000   00000000   00000000   00000000 
-# 0 a: bdffffb0:  00000000   00000000   00000000   bdffffec 
-# 0 a: bdffffc0:  0900012a   bdffffd0   00000020   090000d1 
-# 0 a: bdffffd0: [rrrrrrrr]  00000000   00000000   00000000 
-# 0 a: bdffffe0:  00000000   00000000   00000000   00000000 
-# 0 a: bdfffff0:  00000000   fcfdfeff   00000001   bf000000 
-
-# Stack pointer contains ra is caller's responsibility to over-write with array length.
-
-# actual state:
-# 0 a: bdffff90:  00000000   00000000   00000000   00000000
-# 0 a: bdffffa0:  00000000   00000000   00000000   00000000
-# 0 a: bdffffb0:  00000000   00000000   00000000   bdffffec
-# 0 a: bdffffc0:  0900012a   bdffffd0   00000020   090000d1
-# 0 a: bdffffd0:  00000000  [00000000]  00000000   00000000
-# 0 a: bdffffe0:  00000000   00000000   00000000   00000000
-# 0 a: bdfffff0:  00000020   fcfdfeff   00000001   bf000000
-
-# Couple of issues. But where does the return address disappear to?
-
-## 8:
-
-#? Entry:
-#?     # . prologue
-#?     89/<- %ebp 4/r32/esp
-#?     #
-#?     68/push 0xfcfdfeff/imm32
-#?     b8/copy-to-eax 0x34353637/imm32
-#? $dump-stack0:
-#?     (push-n-zero-bytes 0x20)
-#? $dump-stack9:
-#?     68/push 0x20/imm32
-#? #?     c7 0/subop/copy *esp 0x20/imm32
-#? $dump-stacka:
-#?     b8/copy-to-eax 1/imm32/exit
-#?     cd/syscall 0x80/imm8
-#? 
-#? push-n-zero-bytes:  # n: int
-#? $push-n-zero-bytes:prologue:
-#?     89/<- *Push-n-zero-bytes-ebp 5/r32/ebp  # spill ebp without affecting stack
-#?     89/<- %ebp 4/r32/esp
-#? $push-n-zero-bytes:copy-ra:
-#? $dump-stack1:
-#?     # -- esp = ebp
-#?     50/push-eax
-#? $dump-stack2:
-#?     # -- esp+8 = ebp+4
-#?     # -- esp+4 = ebp
-#?     8b/-> *(esp+4) 0/r32/eax
-#? $dump-stack3:
-#?     2b/subtract *(ebp+4) 4/r32/esp
-#? $dump-stack4:
-#?     # -- esp+4+n = ebp
-#?     89/<- *(esp+4) 0/r32/eax
-#? $dump-stack5:
-#?     58/pop-to-eax
-#?     # -- esp+n = ebp
-#? $push-n-zero-bytes:bulk-cleaning:
-#? $dump-stack6:
-#?     89/<- *Push-n-zero-bytes-esp 4/r32/esp
-#?     81 0/subop/add *Push-n-zero-bytes-esp 4/imm32
-#? $dump-stack7:
-#?     (zero-out *Push-n-zero-bytes-esp *(ebp+4))  # n
-#? $push-n-zero-bytes:epilogue:
-#? $dump-stack8:
-#?     8b/-> *Push-n-zero-bytes-ebp 5/r32/ebp  # restore spill
-#?     c3/return
-#? 
-#? zero-out:  # start: (addr byte), len: int
-#?     # pseudocode:
-#?     #   curr/esi = start
-#?     #   i/ecx = 0
-#?     #   while true
-#?     #     if (i >= len) break
-#?     #     *curr = 0
-#?     #     ++curr
-#?     #     ++i
-#?     #
-#?     # . prologue
-#?     55/push-ebp
-#?     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
-#?     # . save registers
-#?     50/push-eax
-#?     51/push-ecx
-#?     52/push-edx
-#?     56/push-esi
-#?     # curr/esi = start
-#?     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   8/disp8         .                 # copy *(ebp+8) to esi
-#?     # var i/ecx: int = 0
-#?     31/xor                          3/mod/direct    1/rm32/ecx    .           .             .           1/r32/ecx   .               .                 # clear ecx
-#?     # edx = len
-#?     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           2/r32/edx   0xc/disp8       .                 # copy *(ebp+12) to edx
-#? $zero-out:loop:
-#?     # if (i >= len) break
-#?     39/compare                      3/mod/direct    1/rm32/ecx    .           .             .           2/r32/edx   .               .                 # compare ecx with edx
-#?     7d/jump-if->=  $zero-out:end/disp8
-#?     # *curr = 0
-#?     c6          0/subop/copy        0/mod/direct    6/rm32/esi    .           .             .           .           .               0/imm8            # copy byte to *esi
-#?     # ++curr
-#?     46/increment-esi
-#?     # ++i
-#?     41/increment-ecx
-#?     eb/jump  $zero-out:loop/disp8
-#? $zero-out:end:
-#?     # . restore registers
-#?     5e/pop-to-esi
-#?     5a/pop-to-edx
-#?     59/pop-to-ecx
-#?     58/pop-to-eax
-#?     # . epilogue
-#?     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
-#?     5d/pop-to-ebp
-#?     c3/return
-#? 
-#? == data
-#? Push-n-zero-bytes-ebp:  # (addr int)
-#?   0/imm32
-#? Push-n-zero-bytes-esp:  # (addr int)
-#?   0/imm32
-#? == code
-
-# stack at dump-stack0:
-# 0 a: bdffffb0:  00000000   00000000   00000000   00000000 
-# 0 a: bdffffc0:  00000000   00000000   00000000   00000000 
-# 0 a: bdffffd0:  00000000   00000000   00000000   00000000 
-# 0 a: bdffffe0:  00000000   00000000   00000000   00000000 
-# 0 a: bdfffff0:  00000000  [fcfdfeff]  00000001   bf000000 
-
-# desired state after push-n-zero-bytes:
-# 0 a: bdffff90:  00000000   00000000   00000000   00000000 
-# 0 a: bdffffa0:  00000000   00000000   00000000   00000000 
-# 0 a: bdffffb0:  00000000   00000000   00000000   bdffffec 
-# 0 a: bdffffc0:  0900012a   bdffffd0   00000020   090000d1 
-# 0 a: bdffffd0: [rrrrrrrr]  00000000   00000000   00000000 
-# 0 a: bdffffe0:  00000000   00000000   00000000   00000000 
-# 0 a: bdfffff0:  00000000   fcfdfeff   00000001   bf000000 
-
-# actual state:
-# 0 a: bdffff90:  00000000   00000000   00000000   00000000
-# 0 a: bdffffa0:  00000000   00000000   00000000   00000000
-# 0 a: bdffffb0:  00000000   00000000   00000000   bdffffec
-# 0 a: bdffffc0:  09000124   bdffffd0   00000020   090000d1
-# 0 a: bdffffd0: [00000000]  00000000   00000000   00000000
-# 0 a: bdffffe0:  00000000   00000000   00000000   00000000
-# 0 a: bdfffff0:  00000020   fcfdfeff   00000001   bf000000
-
-# Ok, just one diff, at bdfffff0
-
-## 9:
-
-Entry:
-    # . prologue
-    89/<- %ebp 4/r32/esp
-    #
-    68/push 0xfcfdfeff/imm32
-    b8/copy-to-eax 0x34353637/imm32
-$dump-stack0:
-    (push-n-zero-bytes 0x20)
-$dump-stack9:
-    68/push 0x20/imm32
-$dump-stacka:
-    b8/copy-to-eax 1/imm32/exit
-    cd/syscall 0x80/imm8
-
-push-n-zero-bytes:  # n: int
-$push-n-zero-bytes:prologue:
-    89/<- *Push-n-zero-bytes-ebp 5/r32/ebp  # spill ebp without affecting stack
-    89/<- %ebp 4/r32/esp
-$push-n-zero-bytes:copy-ra:
-$dump-stack1:
-    # -- esp = ebp
-    50/push-eax
-$dump-stack2:
-    # -- esp+8 = ebp+4
-    # -- esp+4 = ebp
-    8b/-> *(esp+4) 0/r32/eax
-$dump-stack3:
-    2b/subtract *(ebp+4) 4/r32/esp
-$dump-stack4:
-    # -- esp+4+n = ebp
-    89/<- *(esp+4) 0/r32/eax
-$dump-stack5:
-    58/pop-to-eax
-    # -- esp+n = ebp
-$push-n-zero-bytes:bulk-cleaning:
-$dump-stack6:
-    89/<- *Push-n-zero-bytes-esp 4/r32/esp
-    81 0/subop/add *Push-n-zero-bytes-esp 4/imm32
-$dump-stack7:
-    81 0/subop/add *(ebp+4) 4/imm32
-    (zero-out *Push-n-zero-bytes-esp *(ebp+4))  # n
-$push-n-zero-bytes:epilogue:
-$dump-stack8:
-    8b/-> *Push-n-zero-bytes-ebp 5/r32/ebp  # restore spill
-    c3/return
-
-zero-out:  # start: (addr byte), len: int
-    # pseudocode:
-    #   curr/esi = start
-    #   i/ecx = 0
-    #   while true
-    #     if (i >= len) break
-    #     *curr = 0
-    #     ++curr
-    #     ++i
-    #
-    # . prologue
-    55/push-ebp
-    89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
-    # . save registers
-    50/push-eax
-    51/push-ecx
-    52/push-edx
-    56/push-esi
-    # curr/esi = start
-    8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   8/disp8         .                 # copy *(ebp+8) to esi
-    # var i/ecx: int = 0
-    31/xor                          3/mod/direct    1/rm32/ecx    .           .             .           1/r32/ecx   .               .                 # clear ecx
-    # edx = len
-    8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           2/r32/edx   0xc/disp8       .                 # copy *(ebp+12) to edx
-$zero-out:loop:
-    # if (i >= len) break
-    39/compare                      3/mod/direct    1/rm32/ecx    .           .             .           2/r32/edx   .               .                 # compare ecx with edx
-    7d/jump-if->=  $zero-out:end/disp8
-    # *curr = 0
-    c6          0/subop/copy        0/mod/direct    6/rm32/esi    .           .             .           .           .               0/imm8            # copy byte to *esi
-    # ++curr
-    46/increment-esi
-    # ++i
-    41/increment-ecx
-    eb/jump  $zero-out:loop/disp8
-$zero-out:end:
-    # . restore registers
-    5e/pop-to-esi
-    5a/pop-to-edx
-    59/pop-to-ecx
-    58/pop-to-eax
-    # . epilogue
-    89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
-    5d/pop-to-ebp
-    c3/return
-
-== data
-Push-n-zero-bytes-ebp:  # (addr int)
-  0/imm32
-Push-n-zero-bytes-esp:  # (addr int)
-  0/imm32
-== code
-
-# stack at dump-stack0:
-# 0 a: bdffffb0:  00000000   00000000   00000000   00000000 
-# 0 a: bdffffc0:  00000000   00000000   00000000   00000000 
-# 0 a: bdffffd0:  00000000   00000000   00000000   00000000 
-# 0 a: bdffffe0:  00000000   00000000   00000000   00000000 
-# 0 a: bdfffff0:  00000000  [fcfdfeff]  00000001   bf000000 
-
-# desired state after push-n-zero-bytes:
-# 0 a: bdffff90:  00000000   00000000   00000000   00000000 
-# 0 a: bdffffa0:  00000000   00000000   00000000   00000000 
-# 0 a: bdffffb0:  00000000   00000000   00000000   bdffffec 
-# 0 a: bdffffc0:  0900012a   bdffffd0   00000020   090000d1 
-# 0 a: bdffffd0: [xxxxxxxx]  00000000   00000000   00000000 
-# 0 a: bdffffe0:  00000000   00000000   00000000   00000000 
-# 0 a: bdfffff0:  00000000   fcfdfeff   00000001   bf000000 
-
-# actual state:
-# 0 a: bdffff90:  00000000   00000000   00000000   00000000
-# 0 a: bdffffa0:  00000000   00000000   00000000   00000000
-# 0 a: bdffffb0:  00000000   00000000   00000000   bdffffec
-# 0 a: bdffffc0:  0900012f   bdffffd0   00000024   090000d1
-# 0 a: bdffffd0: [00000000]  00000000   00000000   00000000
-# 0 a: bdffffe0:  00000000   00000000   00000000   00000000
-# 0 a: bdfffff0:  00000000   fcfdfeff   00000001   bf000000