跳到內容

其它語言引入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