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但未保存、恢复其原值,虽不是本次段错误的直接诱因,但会破坏调用者的寄存器状态,引发后续未知问题。
修复方案
正确编译为32位可执行文件
编译链接时明确指定32位目标格式:as -32 power.s -o power.o ld -m elf_i386 power.o -o power修复寄存器保存问题
修改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
相关产品推荐
相关产品推荐

