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

如何在64位NASM汇编中用printf打印命令行参数?(段错误问题)

问题分析与解决

你的代码出现段错误的核心原因是x86-64 System V ABI的栈对齐要求,同时还有一处main函数返回值的不规范处理。

错误细节

  1. 栈对齐问题:x86-64系统调用约定明确要求,调用外部函数(比如printf)时,栈指针rsp必须是16字节对齐的。当main被libc的_start入口调用时,call main指令会将8字节的返回地址压入栈,此时rsp的偏移为8字节,不满足16字节对齐要求。直接调用printf会破坏其内部栈操作逻辑,触发段错误。
  2. 返回值处理:虽然这不是段错误的直接原因,但main函数返回时应明确设置返回值(通常用0表示正常退出)。你的代码中call printf会修改rax的值(printf返回打印的字符数),直接ret会把这个值作为main的返回值,不符合常规编程规范。

修正后的代码

; L26.asm
section .data
    fmt db '%s', 10, 0

section .text
    global main
    extern printf

main:
    mov rdi, fmt                  ; printf第一个参数:格式字符串地址
    mov rsi, [rsi + 8]            ; printf第二个参数:第一个命令行参数(argv[1])
    xor rax, rax                  ; 告诉printf没有浮点数参数
    sub rsp, 8                    ; 调整栈指针到16字节对齐
    call printf
    add rsp, 8                    ; 恢复栈指针
    xor rax, rax                  ; main返回0(正常退出)
    ret

验证步骤

编译和运行命令保持不变:

nasm -f elf64 -o L26.o L26.asm && gcc -no-pie -o L26 L26.o
./L26 foo

此时会正常输出:

foo

补充说明

  • argv是char**类型,指向指针数组,数组中每个元素是字符串指针。[rsi + 8]对应argv[1]——因为64位系统中每个指针占8字节,跳过argv[0](程序名)即可获取第一个命令行参数。
  • xor rax, rax是必须操作:printf是可变参数函数,rax用于告知函数传递的浮点数参数数量(此处为0)。

内容的提问来源于stack exchange,提问作者Caleb Syring

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 16:26:04