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

x64 NASM中调用scanf触发段错误(SIGSEGV)求助

x64 NASM中调用scanf触发段错误(SIGSEGV)求助

哥们,我看了你的代码,问题其实出在几个和x64架构调用约定、数据类型不匹配的关键点上,这也是你一运行就触发段错误的核心原因,咱们一步步理清楚:

问题1:误用32位x86的栈传参方式,违反x64调用约定

x64系统(比如Linux、macOS)遵循的是System V AMD64 ABI调用约定,和32位x86完全不同:

  • 函数的前6个参数是通过寄存器传递的,依次是RDI、RSI、RDX、RCX、R8、R9,超过6个才会用到栈
  • 你还是用32位时代的push栈传参方式,完全不符合x64的要求,这直接导致scanf无法正确读取参数,触发段错误

问题2:数据类型与格式符不匹配,变量空间不足

你要读取的是64位整数,但代码里犯了两个错误:

  • 格式符用了%d,这是对应32位有符号整数的格式符,64位有符号整数应该用%ld
  • 变量A和B用了resd 1,这只分配了4字节(32位双字)的空间,根本存不下64位整数,需要改成resq 1(分配8字节四字空间)

问题3:调用函数前未保证栈16字节对齐

x64调用约定强制要求:调用函数前,RSP必须是16字节对齐的

  • 当main函数被系统调用时,RSP会指向返回地址(占8字节),此时RSP是8字节不对齐的状态
  • 如果不调整RSP到16字节对齐就调用scanf,同样会触发段错误

修正后的代码

global main
extern printf, scanf

section .text
main:
    ; 调整RSP到16字节对齐(进入main时RSP因返回地址占8字节而不对齐)
    sub rsp, 8
    ; 按照x64调用约定传递scanf的参数
    mov rdi, Input_format  ; 第一个参数:格式字符串的地址
    mov rsi, A             ; 第二个参数:存储第一个整数的地址
    mov rdx, B             ; 第三个参数:存储第二个整数的地址
    call scanf
    ; 恢复RSP的对齐状态
    add rsp, 8

    xor eax, eax
    ret

section .data
Input_format: db "%ld %ld", 0  ; %ld对应64位有符号整数

section .bss
A: resq 1  ; 分配8字节空间存储64位整数
B: resq 1

代码修改说明

  1. 改用寄存器传递scanf的参数,完全符合x64调用约定
  2. 修正格式符和变量空间,确保64位整数能正确存储
  3. 调整RSP实现16字节对齐,满足调用前的要求

修正后的代码运行后就能正常等待你输入两个64位整数,不会再触发段错误啦。

备注:内容来源于stack exchange,提问作者Pyramorphix

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.17 12:50:33