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 *(ecx+edx) 2/r32/edx
    42     # var dest/esi: (addr (addr array byte)) = args+4
    43     8d/copy-address *(edi+4) 6/r32/esi
    44     {
    45       # if (curr >= max) break
    46       39/compare %ecx 2/r32/edx
    47       73/jump-if-addr>= break/disp8
    48       # *dest = kernel-string-to-string(*curr)
    49       (kernel-string-to-string Heap *ecx %ebx)
    50       (lookup *ebx *(ebx+4))  # => eax
    51       89/<- *esi 0/r32/eax
    52       # curr += 4
    53       81 0/subop/add %ecx 4/imm32
    54       # dest += 4
    55       81 0/subop/add %esi 4/imm32
    56       #
    57       eb/jump loop/disp8
    58     }
    59     # - run Mu program
    60     (main %edi)  # => ebx
    61     # - exit
    62     (syscall_exit)