如何在64位NASM中调用libc函数(如strcat、printf)
调用libc函数的x86_64寄存器传参规则(System V AMD64 ABI)
你在开发编程语言时调用libc函数,核心要遵循Linux/x86_64平台的System V AMD64调用约定,这是所有C库(包括libc)遵守的标准,下面直接给你讲规则,结合你的代码修正,再扩展到strcat这类函数:
一、核心参数传递规则
- 整数/指针类型参数:前6个参数依次存在
rdi、rsi、rdx、rcx、r8、r9寄存器里,超过6个的参数从右往左压栈。 - 浮点类型参数:前8个浮点参数用
xmm0到xmm7寄存器传递。 - 返回值:整数/指针返回值存在
rax,浮点返回值存在xmm0。 - 寄存器保存:
rbx、rbp、r12~r15是被调用者保存的寄存器(调用libc函数后这些值不会被修改),其他寄存器(比如rdi、rsi)是调用者保存的,调用前要自行保存需要保留的值。
二、你的printf代码问题修正与解释
你现有的printInt、printFloat函数没有正确传递要打印的参数,导致运行时会输出随机值,下面是修正后的版本,同时补充调用示例:
SECTION .data integer_printf: db '%d', 10, 0 float_printf: db '%f', 10, 0 string_format: db '%s', 10, 0 var: db "test", 0 pi: dq 3.1415 ; 双精度浮点数,对应%f格式 SECTION .text extern printf global main ; 调用前需把要打印的整数放入rsi printInt: mov rdi, integer_printf ; 第1个参数:格式串地址 ; 第2个参数已由调用者存入rsi xor rax, rax ; 无浮点参数,rax置0 call printf ret ; 调用前需把要打印的双精度浮点数放入xmm0 printFloat: mov rdi, float_printf ; 第1个参数:格式串地址 mov rax, 1 ; 传递了1个浮点参数,rax设为对应数量 call printf ret ; 调用前需把要打印的字符串指针放入rsi printStr: mov rdi, string_format ; 第1个参数:格式串地址 ; 第2个参数已由调用者存入rsi xor rax, rax call printf ret exit_program: mov rax, 60 ; exit系统调用号 mov rdi, 0 ; 退出码0 syscall ret main: ; 测试打印字符串 mov rsi, var call printStr ; 测试打印整数123 mov rsi, 123 call printInt ; 测试打印浮点数3.1415 movsd xmm0, [rel pi] ; 从内存加载双精度浮点数到xmm0 call printFloat call exit_program
编译命令保持你原来的即可:
nasm -f elf64 -o test.o main.asm && gcc -o test test.o -lc -no-pie
三、调用strcat的示例
strcat的原型是char *strcat(char *dest, const char *src);,按照调用约定:
- 第1个参数
dest(目标字符串地址)放入rdi - 第2个参数
src(源字符串地址)放入rsi - 返回值是
dest的指针,存在rax中
示例代码片段:
SECTION .data dest: db "Hello ", 0 src: db "World!", 0 SECTION .text extern strcat ; 在main中调用strcat lea rdi, [rel dest] ; 传入dest地址到rdi lea rsi, [rel src] ; 传入src地址到rsi call strcat ; rax现在指向拼接后的dest ; 打印拼接结果 mov rsi, rax call printStr
四、关键注意点
- 调用printf时,如果用到浮点格式符(%f、%lf等),必须把rax设置为传递的浮点参数数量(即用到的xmm寄存器个数),否则会导致栈布局混乱,出现错误输出或崩溃。
- 所有字符串参数必须以
\0结尾,符合C语言的字符串标准,否则libc函数会读取内存直到遇到0,引发未定义行为。 - x86_64 ABI要求调用函数前栈必须是16字节对齐的,gcc链接main函数时会自动处理栈对齐,但如果你自己写的函数调用前栈不对齐,需要手动调整(比如
sub rsp, 8)。
内容的提问来源于stack exchange,提问作者Hrodebert
相关产品推荐
相关产品推荐

