; vim: ft=nasm
bits 64
%include "syscall.s"
global _start:function
extern _boot
extern entry
_start:
mov rbp, 0 ; zero the stack base ptr.
; attempted fix for a difficult-to-
; reproduce bug
mov rdi, 0 ; zero rdi - because argc
; is 32 bits long, we have to store
; its value in the lower half of rdi.
; this ensures that the upper half is
; zeroed as well.
mov edi, [rsp + 0] ; sizeof arguments
; first argument to _boot(): argc
; this is a 32-bit signed(??) integer
; that is equal to the number of
; elements in argv (see below). it is
; not strictly necessary, because argv
; is per spec always null-terminated,
; but we pass it just in case.
lea rsi, [rsp + 8] ; &arguments
; 2nd argument to _boot(): ptr to argv
; this points to an array of strings
; containing the program's command line
; arguments. _boot() does not need to
; parse this, but it does need to store
; it in the structure passed to main()
lea rdx, [rsp + 16] ; &environment
; third argument to _boot(): ptr to envp
; this points to the list of environment
; variables for the running program. it
; is the responsibility of _boot to parse
; this list and arrange it into a set of
; legible and useful C arrays.
mov rax, 0 ; zero out %rax
; this is required by the C ABI, and is
; reputedly necessary for compatibility
; with icc, intel's own proprietary C
; compiler.
call _boot ; invoke the start function
; that will set up the runtime and
; construct the necessary structures
; that will be bassed to libc.
; boot has returned and left its
; return value in the register %rax.
; regardless of the size of the
; return value of main(), _boot always
; returns the system word length.
mov sys.reg.1, sys.reg.ret ; fill in
; the return value as exit's argument
mov sys.reg.0, 60 ; set %rax to
; the syscall number of exit
sys.call ; invoke the kernel