diff options
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 + |