https://github.com/akkartik/mu/blob/main/linux/mu-init.subx
 1 # Initialize the minimal runtime for Mu programs.
 2 #
 3 # See translate_mu for how this file is used.
 4 #
 5 # Mu programs start at a function called 'main' with this signature:
 6 #   fn main args: (addr array addr array byte) -> _/ebx: int
 7 # If your program doesn't need commandline arguments you can drop it:
 8 #   fn main -> _/ebx: int
 9 #
10 # Notice that the output must be in ebx, so that the exit() syscall can pick
11 # it up.
12 
13 == code
14 
15 Entry:
16     # we don't use ebp in Entry; just initialize it
17     bd/copy-to-ebp 0/imm32
18     # - save argc and argv
19     # var argc-and-argv/esi
20     89/<- %esi 4/r32/esp
21 $Entry:initialize-heap:
22     # - initialize the heap
23     (new-segment *Heap-size Heap)
24 $Entry:initialize-args:
25     # - convert argv from null-terminated 'kernel' strings to length-prefixed Mu strings
26     # var argc/edx: int
27     8b/-> *esi 2/r32/edx
28     # argc is in words; convert it to bytes
29     c1/shift 4/subop/left %edx 2/imm8
30     # var tmp/ebx: handle
31     68/push 0/imm32
32     68/push 0/imm32
33     89/<- %ebx 4/r32/esp
34     # var args/edi: (addr array (addr array byte))
35     (allocate-array Heap %edx %ebx)
36     (lookup *ebx *(ebx+4))  # => eax
37     89/<- %edi 0/r32/eax
38     # var curr/ecx: (addr kernel-string) = argv
39     8d/copy-address *(esi+4) 1/r32/ecx
40     # var max/edx: (addr kernel-string) = argv+4+argc
41     8d/copy-address *(ec