You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

编译与运行步骤

  1. 编译sys_print.asm:
$ nasm -f macho64 sys_print.asm -o libraryObjects/sys_print.o
  1. 编译并链接主程序:
$ nasm -f macho64 -o main.o main.asm
$ gcc -o hello main.o sys_print.o   
  1. 运行后无输出:
$ ./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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 17:02:57