跳转到内容

其它语言引入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代码和这个

Terminal window
nasm -f elf64 file.asm -o file.o && gcc call_nasm.c file.o -o call_nasm
./call_nasm

需要注意的是根据ABI规定寄存器分为呼叫者保存(Caller-saved)和被呼叫者保存( Callee-saved)

使用call回来后以下寄存器的内容是可能被改变的
rax, rcx, rdx, rsi, rdi, r8, r9, r10, r11, rflags

被call进入后的函数应该保存以下寄存器的值不能破坏
rbx, rbp, rsp, r12, r13, r14, r15
如果要使用这几个寄存器一般在开头push最后结尾pop还原,像是这样

func:
push rbx
push rbp
; ......
pop rbp
pop rbx
ret