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

GNU x86汇编实现幂函数时触发Segmentation fault (core dumped)

x64 Linux下32位汇编幂函数段错误原因分析

核心问题:运行模式不匹配导致栈与寄存器混乱

你的代码用.code32声明为32位x86汇编,但运行在x86_64架构的Linux系统上,且未正确编译为32位可执行文件,直接以64位模式运行,这是段错误的根本原因:

  • 寄存器与栈布局错位:64位模式下CPU默认使用64位寄存器(如%rbp、%rbx),而你的32位代码仅操作寄存器低32位。同时64位模式要求栈按8字节对齐,但你用pushl(4字节压栈)传递参数,导致power函数中访问8(%ebp)时,实际指向无效内存区域,触发段错误。gdb显示带r后缀的寄存器,就是程序在64位模式下运行的直接证明。
  • 编译链接未指定32位目标:x64系统的汇编器和链接器默认生成64位可执行文件,即便你写了.code32,也仅能让汇编器生成32位指令,但程序整体仍以64位模式加载执行,指令与运行环境完全不兼容。

次要问题:违反32位调用约定

在32位x86 Linux调用约定中,%ebx属于被调用者保存寄存器,你的power函数直接修改%ebx但未保存、恢复其原值,虽不是本次段错误的直接诱因,但会破坏调用者的寄存器状态,引发后续未知问题。

修复方案

  1. 正确编译为32位可执行文件
    编译链接时明确指定32位目标格式:

    as -32 power.s -o power.o
    ld -m elf_i386 power.o -o power
    
  2. 修复寄存器保存问题
    修改power函数,在开头保存%ebx,结尾恢复:

    .type power, @function
    power:
      pushl %ebp
      movl %esp, %ebp
      pushl %ebx          # 保存被调用者保存寄存器
      subl $4, %esp
      movl 8(%ebp), %ebx
      movl 12(%ebp), %ecx
      movl %ebx, -4(%ebp)
    
    power_loop_start:
      cmpl $1, %ecx
      je end_power
      movl -4(%ebp), %eax
      imull %ebx, %eax
      movl %eax, -4(%ebp) 
      decl %ecx
      jmp power_loop_start
    
    end_power:
      movl -4(%ebp), %eax
      movl %ebp, %esp 
      popl %ebx           # 恢复寄存器
      popl %ebp 
      ret
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 10:43:18