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

自制编译器生成x86汇编函数调用后触发Segmentation fault求助

问题排查结果

1. 核心崩溃原因:局部变量栈偏移错误,覆盖栈上保存的rbp值

你在函数中为局部变量/参数分配栈空间后,使用了完全错误的内存地址写入:

  • function_main中通过sub rsp,4分配了4字节栈空间存储变量f,正确的访问地址应为[rbp-4],你当前使用的[rbp-0](等价于[rbp])指向的是入栈时保存的旧rbp值,写入10直接覆盖了该值。
  • function_func中存在完全相同的问题,分配4字节存储参数a,却写入[rbp-0]覆盖旧rbp值。
    当函数执行到pop rbp时,取出的rbp是被篡改的错误值,后续ret指令会将非法地址作为返回地址跳转,直接触发段错误,这就是第一次调用func返回后崩溃的根本原因。

2. 违反x86-64 System V ABI寄存器规则

rbx属于被调用者保存寄存器,在function_main中直接修改rbx前没有提前入栈保存,使用后也没有恢复,会导致上层调用方的寄存器上下文被破坏,引发不可预期的错误。如果仅需要临时存储常量2,建议改用rcx这类调用者保存寄存器,无需额外保存操作。

3. 64位除法未初始化rdx寄存器

你使用idiv rbx执行64位有符号除法时,被除数默认是rdx:rax寄存器对,你没有提前对eax做符号扩展填充rdx,rdx中的垃圾值会导致除法结果错误,甚至触发除法溢出异常。如果只需要做32位除法,可改为使用idiv ebx,同时提前执行cdq指令符号扩展eax到edx即可。

4. 链接命令参数错误

你当前使用的链接命令ld -g ./test9.lv.asm.o a.out是错误的,该命令会把已存在的a.out作为输入文件参与链接,正确的命令应该指定输出参数:ld -g ./test9.lv.asm.o -o a.out。

修复后可正常运行的汇编代码示例
section .text
global _start
_start:
    call function_main
    mov rdi, rax
    mov rax, 60
    syscall

global function_main
function_main:
    push rbp
    mov rbp, rsp
    sub rsp, 4
    mov rax, 10
    mov DWORD[rbp-4], eax ; 修正偏移
    mov eax, DWORD[rbp-4]
    mov rdi, rax
    call function_func
    push rax
    mov eax, DWORD[rbp-4]
    cdq ; 符号扩展eax到edx
    mov ecx, 2 ; 改用调用者保存寄存器rcx,无需额外保存
    idiv ecx
    mov rdi, rax
    call function_func
    mov rcx, rax
    pop rax
    sub rax, rcx
    mov rsp, rbp
    pop rbp
    ret

global function_func
function_func:
    push rbp
    mov rbp, rsp
    sub rsp, 4
    mov DWORD[rbp-4], edi ; 修正偏移
    mov eax, DWORD[rbp-4]
    mov rsp, rbp
    pop rbp
    ret

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 13:39:02