https://github.com/akkartik/mu/blob/master/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)) -> exit-status/ebx: int
 7 # If your program doesn't need commandline arguments you can drop it:
 8 #   fn main -> exit-status/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/eax: handle
31     68/push 0/imm32
32     68/push 0/imm32
33     89/<- %eax 4/r32/esp
34     # var args/edi: (addr array (addr array byte))
35     (allocate-array Heap %edx %eax)
36     8b/-> *(eax+4) 7/r32/edi
37     # var curr/ecx: (addr kernel-string) = argv
38     8d/copy-address *(esi+4) 1/r32/ecx
39     # var max/edx: (addr kernel-string) = argv+4+argc
40     8d/copy-address *(ecx+edx) 2/r32/edx
41     # var dest/esi: (addr (addr array byte)) = args+4
42     8d/copy-address *(edi+4) 6/r32/esi
43     {
44       # if (curr >= max) break
45       39/compare %ecx 2/r32/edx
46       73/jump-if-addr>= break/disp8
47       # *dest = kernel-string-to-string(*curr)
48       (kernel-string-to-string Heap *ecx)  # => eax
49       89/<- *esi 0/r32/eax
50       # curr += 4
51       81 0/subop/add %ecx 4/imm32
52       # dest += 4
53       81 0/subop/add %esi 4/imm32
54       #
55       eb/jump loop/disp8
56     }
57     # - run Mu program
58     (main %edi)  # => ebx
59     # - exit
60     (syscall_exit)