kvisc/ka/ABI

132 lines
3.9 KiB
Plaintext
Raw Normal View History

2019-06-15 20:21:38 +02:00
# The OS/K Team licenses this file to you under the MIT license.
# See the LICENSE file in the project root for more information.
#------------------------------------------------------------------------------#
1. STACK
Stack grows downward. 'rbp' and 'rsp' are both used.
2019-06-20 12:31:36 +02:00
The lowest stack frame is marked by having 'rbp' = 0.
There is a 128-bytes red zone below 'rsp'.
2019-06-15 20:21:38 +02:00
A function's assembly code looks like this:
label:
enter N
...
...
...
leave
ret
2019-06-16 12:48:30 +02:00
'N' is the number of local variables used by the function.
2019-06-15 20:21:38 +02:00
2019-07-09 20:16:35 +02:00
The above code is equivalent to the following, but faster:
2019-06-15 20:21:38 +02:00
label:
2019-07-09 20:16:35 +02:00
push rbp
mov rbp, rsp
sub rsp, N*8
2019-06-15 20:21:38 +02:00
...
...
...
2019-07-09 20:16:35 +02:00
mov rsp, rbp
pop rbp
2019-06-15 20:21:38 +02:00
ret
Between the 'enter' and the 'leave', the stack looks like this:
. .
. .
. (caller's) .
|---------------|
| saved rip | rbp+8
| saved rbp | rbp+0
| . | rsp+(N*8) \
| . | ... |
| . | ... |
| . | ... |- Local variables
| . | rsp+16 |
| . | rsp+8 |
| . | rsp+0 /
|---------------|
2019-07-01 21:46:36 +02:00
. (red zone) .
2019-06-15 20:21:38 +02:00
. .
. .
'enter' and 'leave' can be omitted if ALL the following hold:
the function
- uses no local variables (on the stack)
- never uses any function that changes 'rbp' nor 'rsp',
aside from 'call' and 'ret'
2019-06-16 14:01:58 +02:00
You can never omit 'enter' without omitting 'leave', and vice-versa.
2019-06-15 20:21:38 +02:00
#------------------------------------------------------------------------------#
2. CALLING CONVENTION
No matter whether 'enter' and 'leave' were ommited or not, the following must
hold true whenever a function is entered or exited from:
- 'rbp' must be 8-bytes aligned
- 'rsp' must be 8-bytes aligned
- the DF flag must be cleared
Aside from the DF flag, a function cannot assume anything about the state
of the flags in the FLG register.
Passing parameters is done using the following registers, in that order:
2019-07-15 20:47:44 +02:00
a0-a7
2019-06-15 20:21:38 +02:00
2019-06-17 20:59:30 +02:00
The stack is never used for argument passing, except for variadic functions,
cf the next section. If you need to pass large structures of data, pass
their address in an appropriate register.
2019-06-15 20:21:38 +02:00
Return values are passed in 'rax'. If the return value does not fit
and require more registers, use the following registers, in that order:
2019-07-09 20:16:35 +02:00
rax, rdx
2019-06-15 20:21:38 +02:00
The following registers are volatile; the calling function cannot assume
that they will be left unmodified by the called function:
2019-07-15 20:47:44 +02:00
rax, rcx, rdx, r8-r15, a0-a7
2019-06-15 20:21:38 +02:00
The following registers are nonvolatile; the called function must preserve them:
2019-07-15 20:47:44 +02:00
rbx, rsi, rdi, n0-n7, rbp, rsp
2019-06-15 20:21:38 +02:00
#------------------------------------------------------------------------------#
2019-06-17 20:59:30 +02:00
3. VARIADIC FUNCTIONS
To call a variadic function, do this:
sub rsp, nargs * 8
mov [rsp], arg0
...
...
...
mov [rsp+(N*8)], argN
call variadic_func
add rsp, nargs * 8
To the variadic function, argN can be accessed the following way:
2019-06-21 22:19:55 +02:00
mov reg, [rbp+N*8+16]
2019-06-17 20:59:30 +02:00
For instance:
2019-06-21 22:19:55 +02:00
mov rax, [rbp+16] ; arg0
mov rdx, [rbp+24] ; arg1
2019-06-17 20:59:30 +02:00
It is recommended to use the reg+reg*imm16+imm16 memory format:
2019-06-21 22:19:55 +02:00
mov rax, [rbp+rcx*8+16] ; accesses arg#rcx
2019-06-17 20:59:30 +02:00
The 'va_list' type can be regarded as a pointer to the
variadic function's rbp+16
#------------------------------------------------------------------------------#
4. SPECIAL REGISTERS
2019-06-15 20:21:38 +02:00
The 'inv' register cannot be referenced by machine code except when specified
as an offset register in the [reg+reg(*/+...)] memory formats; in these case,
'inv' can be assumed to be always null.
2019-07-15 20:47:44 +02:00
(TO BE COMPLETED)
2019-06-15 20:21:38 +02:00
#------------------------------------------------------------------------------#