mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
82 lines
1.5 KiB
NASM
82 lines
1.5 KiB
NASM
section .text
|
|
global arch_context_switch
|
|
arch_context_switch:
|
|
; rdi is the pointer to the context struct
|
|
mov rsp, rdi
|
|
|
|
add rsp, 24 ; cr2 gs and fs are not popped.
|
|
pop rax
|
|
mov es,rax
|
|
pop rax
|
|
mov ds,rax
|
|
pop rax
|
|
pop rbx
|
|
pop rcx
|
|
pop rdx
|
|
pop r8
|
|
pop r9
|
|
pop r10
|
|
pop r11
|
|
pop r12
|
|
pop r13
|
|
pop r14
|
|
pop r15
|
|
pop rdi
|
|
pop rsi
|
|
pop rbp
|
|
add rsp,8 ; remove error code
|
|
|
|
; check if swapgs is needed
|
|
cmp qword [rsp+8], 0x18
|
|
jne .notneeded2
|
|
swapgs
|
|
.notneeded2:
|
|
o64 iret
|
|
|
|
; saves context on the stack and passes as the argument to a function
|
|
; since this uses the C system V abi, some registers can be clobbered (in this case, rsi and r11)
|
|
; rdi has the pointer to the function to call
|
|
; if the main function returns, just return normally
|
|
global arch_context_saveandcall
|
|
arch_context_saveandcall:
|
|
mov r11, [rsp] ; save return address on scratch register
|
|
mov rsi, rsp
|
|
add rsi, 8 ; stack pointer before the call instruction
|
|
|
|
push qword 0x10 ; SS
|
|
push rsi ; RSP
|
|
pushf ; movs and pushes don't affect flags
|
|
push qword 0x08 ; CS
|
|
push r11 ; return address
|
|
sub rsp, 8 ; error code
|
|
push rbp
|
|
push rsi
|
|
push rdi
|
|
push r15
|
|
push r14
|
|
push r13
|
|
push r12
|
|
push r11
|
|
push r10
|
|
push r9
|
|
push r8
|
|
push rdx
|
|
push rcx
|
|
push rbx
|
|
push rax
|
|
push qword 0x10 ; ES
|
|
push qword 0x10 ; DS
|
|
push qword 0 ; FS
|
|
push qword 0 ; GS
|
|
sub rsp, 8 ; cr2
|
|
|
|
|
|
mov r11, rdi ; save function to call
|
|
mov rdi, rsp ; first argument is the context struct
|
|
push rsi ; save old stack
|
|
call r11 ; jump to the desired function
|
|
|
|
pop rsp ; restore old stack
|
|
sub rsp, 8
|
|
ret
|