diff options
| author | Irene Knapp <ireneista@irenes.space> | 2026-05-16 13:53:08 -0700 |
|---|---|---|
| committer | Irene Knapp <ireneista@irenes.space> | 2026-05-16 13:53:08 -0700 |
| commit | fe3de0772dac094b94f8de89efbb815a62b1a2fa (patch) | |
| tree | cf5fca8004005f5015a6dcfc7c25fd8ff2879d3d /linux.e | |
| parent | f4112a05de8bf4c69a7abb9817c7ca70be9f7fb5 (diff) | |
implement more internal words
Force-Push: yes Change-Id: I273879e9d05260db0603bc5a36970e240f3e366a
Diffstat (limited to 'linux.e')
| -rw-r--r-- | linux.e | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/linux.e b/linux.e new file mode 100644 index 0000000..ce0b9b7 --- /dev/null +++ b/linux.e @@ -0,0 +1,69 @@ +~ ~~~~~~~~~~~~~~~~~~ +~ ~~ System calls ~~ +~ ~~~~~~~~~~~~~~~~~~ +~ +~ The kernel preserves every register except rax, rcx, and r11. The system +~ call number goes in rax, as does the return value. Parameters go in rdi, +~ rsi, rdx, r10, r8, and r9, in that order. [SysV] A.2.1. +~ +~ Notice that rsi is our control stack, so we have to save it (for +~ syscalls with at least two parameters). We can use the value stack to do +~ that, since rsp is preserved. We don't save other registers because our +~ caller should do that, if it cares. +~ + +~ This does the Linux exit() system call, passing it an exit code taken +~ from the stack. It does not return. +~ +~ (exit code -- *) +: sys-exit + [ here @ + 60 :rax mov-reg64-imm64 ~ syscall number + :rdi pop-reg64 ~ exit code + syscall + + ~ In the event we're still here, let's minimize confusion. + hlt + + ~ This one, uniquely, doesn't need to be followed by the "next" macro. It + ~ is, though, since ;asm does that anyway. + here ! ] ;asm + + +~ This does the Linux write() system call, passing it an address from the +~ top of the stack and a length from the second position on the stack. It +~ writes to file descriptor 1, which is stdout. +~ +~ For our length parameter, we can pop directly from the stack into rdx, +~ which directly becomes the syscall parameter. For our address parameter, +~ the syscall wants it in rsi, which we also care about, so we have to do a +~ little juggling. +~ +~ (length to write, base address -- *) +: sys-write + [ here @ + :rcx pop-reg64 ~ address from stack + :rdx pop-reg64 ~ length from stack, passed directly + :rsi push-reg64 ~ save rsi + 1 :rax mov-reg64-imm64 ~ syscall number + 1 :rdi mov-reg64-imm64 ~ file descriptor + :rcx :rsi mov-reg64-reg64 ~ pass address + syscall + :rsi pop-reg64 ~ restore rsi + here ! ] ;asm + + +~ (length to read, base address -- *) +: sys-read + [ here @ + :rcx pop-reg64 ~ address from stack + :rdx pop-reg64 ~ length from stack, passed directly + :rsi push-reg64 ~ save rsi + 0 :rax mov-reg64-imm64 ~ syscall number + 0 :rdi mov-reg64-imm64 ~ file descriptor + :rcx :rsi mov-reg64-reg64 ~ pass address + syscall + :rsi pop-reg64 ~ restore rsi + :rax push-reg64 ~ return length + here ! ] ;asm + |