summary refs log tree commit diff
path: root/linux.e
blob: c7e9bb360c6b7764f37cd1b8436c9ec5c9128815 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~ ~~ System calls for the Linux kernel ~~
~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~
~   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