+ mov edi, [gMultibootMagic - KERNEL_BASE]
+ mov esi, [gMultibootPtr - KERNEL_BASE]
+ call kmain
+
+ cli
+.hlt:
+ hlt
+ jmp .hlt
+
+[global GetCPUNum]
+GetCPUNum:
+ xor rax, rax
+ str ax
+ sub ax, 0x38 ; TSS Base
+ shr ax, 4 ; One 16-byte TSS per CPU
+ ret
+
+KSTACK_USERSTATE_SIZE equ (5+2+16+2)*8 ; IRET, ErrorNum, ErrorCode, GPRs, FS&GS
+[global Proc_ReturnToUser]
+Proc_ReturnToUser:
+ ; RDI - Handler
+ ; RSI - Kernel Stack
+ ; RDX - Signal num
+
+ ;
+ ; NOTE: This can cause corruption if the signal happens while the user
+ ; has called a kernel operation.
+ ; Good thing this can only be called on a user fault.
+ ;
+
+ xchg bx, bx
+ ; Get and alter User SP
+ mov rcx, [rsi-0x20] ; Get user SP
+ xor eax, eax
+ mov [rcx-16], rax
+ sub rcx, 16
+
+ ; Drop down to user mode
+ cli
+ mov rsp, rcx ; Set SP
+ mov rcx, rdi ; SYSRET IP
+
+ mov rdi, rdx ; Argument for handler
+ mov r11, 0x202 ; RFlags
+ db 0x48
+ sysret
+
+; int CallWithArgArray(void *Ptr, int NArgs, Uint *Args)
+; Call a function passing the array as arguments
+[global CallWithArgArray]
+CallWithArgArray:
+ push rbp
+ mov rbp, rsp
+ push r10
+ push r11
+
+ mov [rbp+2*8], rdi ; Save Ptr to stack
+
+ mov r11, rsi ; NArgs
+ mov r10, rdx ; Args
+
+ ; Arg 1: RDI
+ mov rdi, [r10]
+ add r10, 8
+ dec r11
+ jz .call
+ ; Arg 2: RSI
+ mov rsi, [r10]
+ add r10, 8
+ dec r11
+ jz .call
+ ; Arg 3: RDX
+ mov rdx, [r10]
+ add r10, 8
+ dec r11
+ jz .call
+ ; Arg 4: RCX
+ mov rcx, [r10]
+ add r10, 8
+ dec r11
+ jz .call
+ ; Arg 5: R8
+ mov r8, [r10]
+ add r10, 8
+ dec r11
+ jz .call
+ ; Arg 6: R9
+ mov r9, [r10]
+ add r10, 8
+ dec r11
+ jz .call
+ ; No support for more