其它语言引入Nasm自定义函数
C/C++可以使用 extern 来引用外部函数,在link时必须包含该库
Python用ctype.CDLL()载入已经做成.so/.dll的动态链接函数库
遵循着函数参数顺序和本篇底下的寄存器保存规范
以下是一个Nasm找n个数字最大值的例子,int64_t max_n(n, n1, n2, ...)
global max_n
section .text
max_n: dec rdi jz end cmp rsi, rdx cmovl rsi, rdx ; 上面cmp小于则mov dec rdi jz end cmp rsi, rcx cmovl rsi, rcx dec rdi jz end cmp rsi, r8 cmovl rsi, r8 dec rdi jz end cmp rsi, r9 cmovl rsi, r9 dec rdi jz end mov rcx, 1
loop: inc rcx cmp rsi, [rsp+rcx*8] cmovl rsi, [rsp+rcx*8] dec rdi jnz loop
end: mov rax, rsi ret然后在C语言引用max_n函数
#include <stdio.h>#include <inttypes.h>
extern int64_t max_n(int64_t, ...);
int main() { printf("%ld\n", max_n(10, 130, 2, 1, 5, 6, 95, 600, 105, 120, 100)); return 0;}汇编nasm <- 用gcc编译链接C代码和这个
nasm -f elf64 file.asm -o file.o && gcc call_nasm.c file.o -o call_nasm./call_nasmCaller/Callee saved
Section titled “Caller/Callee saved”需要注意的是根据ABI规定寄存器分为呼叫者保存(Caller-saved)和被呼叫者保存( Callee-saved)
Caller-saved
Section titled “Caller-saved”使用call回来后以下寄存器的内容是可能被改变的
rax, rcx, rdx, rsi, rdi, r8, r9, r10, r11, rflags
Callee-saved
Section titled “Callee-saved”被call进入后的函数应该保存以下寄存器的值不能破坏
rbx, rbp, rsp, r12, r13, r14, r15
如果要使用这几个寄存器一般在开头push最后结尾pop还原,像是这样
func: push rbx push rbp ; ...... pop rbp pop rbx ret