x86_64汇编跨文件调用打印函数无输出问题求助
问题排查:汇编打印函数无输出
环境信息
- macOS Ventura系统,Intel双核CPU
sys_print函数代码
global sys_print sys_print: ; store the stack pointer push rbp mov rbp, rsp ; get the string to print mov rdi, [rbp + 0x18] ; get length of the string mov rsi, [rbp + 0x10] ; print the string mov rax, 0x2000004 mov rdx, rsi syscall ; restore the stack pointer pop rbp ret
主程序代码
extern sys_print global _main section .data hello db 'Hello, world!', 0x0a, 0 len equ $ - hello section .text align 16 _main: lea rdi, [rel hello] mov rsi, len push rdi push rsi call sys_print add rsp, 16 mov eax, 0x2000001 xor edi, edi syscall
编译与运行步骤
- 编译sys_print.asm:
$ nasm -f macho64 sys_print.asm -o libraryObjects/sys_print.o
- 编译并链接主程序:
$ nasm -f macho64 -o main.o main.asm $ gcc -o hello main.o sys_print.o
- 运行后无输出:
$ ./hello $
问题分析与修复
核心问题1:系统调用参数缺失
macOS Mach-O 64位环境下,write系统调用(编号0x2000004)的参数约定为:
rdi:文件描述符(标准输出stdout对应1)rsi:字符串内存地址rdx:字符串长度
原sys_print函数未设置rdi=1,系统调用无法确定输出目标,导致无内容输出。
核心问题2:栈帧参数偏移错误
主程序调用时先push长度rsi,再push字符串指针rdi,进入sys_print建立栈帧后,栈布局为:
[rbp+0x10]:返回地址[rbp+0x18]:第一个push的值(字符串长度)[rbp+0x20]:第二个push的值(字符串指针)
原代码读取参数的偏移完全错误,导致传递的字符串地址和长度混乱。
修复后的sys_print函数(栈传参版本)
global sys_print sys_print: push rbp mov rbp, rsp ; 读取栈中正确位置的参数 mov rsi, [rbp + 0x20] ; 字符串指针 mov rdx, [rbp + 0x18] ; 字符串长度 mov rdi, 1 ; 指定输出到标准输出 mov rax, 0x2000004 syscall pop rbp ret
更规范的寄存器传参版本(推荐)
遵循macOS采用的System V AMD64调用约定,直接用寄存器传参,避免栈操作错误:
sys_print函数修改
global sys_print sys_print: ; 直接使用寄存器传参:rdi=字符串指针,rsi=字符串长度 mov rdx, rsi mov rsi, rdi mov rdi, 1 ; 标准输出文件描述符 mov rax, 0x2000004 syscall ret
主程序调用部分修改
_main: lea rdi, [rel hello] mov rsi, len call sys_print ; 直接寄存器传参,无需栈操作 ; 移除 add rsp,16 mov eax, 0x2000001 xor edi, edi syscall
修改后重新编译运行,即可正常输出Hello, world!。
内容的提问来源于stack exchange,提问作者Fab boy
相关产品推荐
相关产品推荐

