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
|