Calling Functions from Assembly
CS 301 Lecture, Dr. Lawlor
The standard 64-bit "function call interface" is:
- Return value goes in eax (32-bit "int" return value) or rax (64-bit "long" return value).
- The first function parameter goes into rdi (second parameter goes in rsi, then rdx, rcx, r8d, r9d, and then stranger places).
- You can freely overwrite the values in rax, rcx, rdx, rsi, rdi, and r8-r11 (the "scratch" registers).
- You can't change the values in rbx, rbp, rsp, and r12-r15 (the "saved" or "preserved" registers).
This seems somewhat annoying: if you call another function, like
print_long, it might trash everything in rax, rcx, rdx, etc. It
won't mess with the preserved registers rbx,rbp, etc, but you can't mess with them either!
For example, to call the NetRun builtin function print_int with the integer 3, I just make sure that register rdi contains this value:
mov rdi,3 ; function's first parameter
extern print_int
call print_int
ret
(Try this in NetRun now!)
"edi" is the 32-bit version of the 64-bit "rdi". Since print_int expects a 32-bit value, this works exactly the same way:
mov edi,3 ; function's first parameter (32-bit)
extern print_int
call print_int
ret
(Try this in NetRun now!)
To read an integer, add 3, and print it, I just need to move the result from eax into edi:
extern read_input
call read_input
; eax contains return value from read_input
add eax,3
mov edi,eax
; edi contains parameter for print_int
extern print_int
call print_int
ret
(Try this in NetRun now!)
To call a function with two parameters, put the first parameter in rdi, and the second in rsi:
mov rdi,0xdeadbeef ; pointer to integers
mov rsi,0 ; number of ints to print
extern iarray_print
call iarray_print
ret
(Try this in NetRun now!)
Keep in mind calling any function can trash all the scratch registers!