https://github.com/akkartik/mu/blob/main/linux/302stack_allocate.subx
 1 # A function which pushes n zeros on the stack.
 2 # Really only intended to be called from code generated by mu.subx (for array
 3 # vars on the stack).
 4 
 5 == code
 6 
 7 #? Entry:
 8 #?     # . prologue
 9 #?     89/<- %ebp 4/r32/esp
10 #?     #
11 #?     68/push 0xfcfdfeff/imm32
12 #?     b8/copy-to-eax 0x34353637/imm32
13 #? $dump-stack0:
14 #?     (push-n-zero-bytes 4)
15 #?     68/push 0x20/imm32
16 #? $dump-stack9:
17 #?     b8/copy-to-eax 1/imm32/exit
18 #?     cd/syscall 0x80/imm8
19 
20 # This is not a regular function, so it won't be idiomatic.
21 # Registers must be properly restored.
22 # Registers can be spilled, but that modifies the stack and needs to be
23 # cleaned up.
24 
25 # Overhead:
26 #   62 + n*6 instructions to push n bytes.
27 # If we just emitted code to push n zeroes, it would be:
28 #   5 bytes for 4 zero bytes, so 1.25 bytes per zero. And that's not even
29 #   instructions.
30 # But on the other hand it would destroy the instruction cache, where this
31 # approach requires 15 instructions, fixed.
32 
33 # n must be positive
34 push-n-zero-bytes:  # n: int
35 $push-n-zero-bytes:prologue:
36     89/<- *Push-n-zero-bytes-ebp 5/r32/ebp  # spill ebp without affecting stack
37     89/<- %ebp 4/r32/esp
38 $push-n-zero-bytes:copy-ra:
39     # -- esp = ebp
40     89/<- *Push-n-zero-bytes-eax 0/r32/eax
41     8b/-> *esp 0/r32/eax
42     2b/subtract *(ebp+4) 4/r32/esp
43     # -- esp+n = ebp
44     89/<- *esp 0/r32/eax
45     8b/-> *Push-n-zero-bytes-eax 0/r32/eax
46 $push-n-zero-bytes:bulk-cleaning:
47     89/<- *Push-n-zero-bytes-esp 4/r32/esp
48     81 0/subop/add *Push-n-zero-bytes-esp 4/imm32
49     81 0/subop/add *(ebp+4) 4/imm32
50     (zero-out *Push-n-zero-bytes-esp *(ebp+4))  # n+4
51 $push-n-zero-bytes:epilogue:
52     8b/-> *Push-n-zero-bytes-ebp 5/r32/ebp  # restore spill
53     c3/return
54 
55 == data
56 Push-n-zero-bytes-ebp:  # (addr int)
57   0/imm32
58 Push-n-zero-bytes-esp:  # (addr int)
59   0/imm32
60 Push-n-zero-bytes-eax:
61   0/imm32