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

简单内联汇编程序在GCC 5.0下触发Segmentation Fault:11的修复方案

修复GCC内联汇编square函数的段错误问题

环境与原始代码

在配备Core 2 Duo的iMac(Mac OS X 10.7系统)上,使用GCC 5.0.0编译以下代码:

#include <stdio.h>

int square (int n) {
  __asm__("mov %eax, n"
      "mul %eax");
}

int main(void) {
  printf("\nSquare of 4 is %i", square(4));
  /* Calling square gives Segmentation fault: 11 error */
  return 0;
}

编译与运行报错

编译命令:
gcc -o assem -DDEBUG=9 -ansi -pedantic -Wall -g assem.c

编译时出现警告:

assem.c: In function ‘square’:
assem.c:6:1: warning: control reaches end of non-void function [-Wreturn-type]
 }
 ^
assem.c:4:Can't relocate expression. Absolute 0 assumed.

Compilation finished at Mon Jul 25 18:23:47

运行程序触发Segmentation fault:11错误,用户查阅10余个相关问题未解决。

后续尝试

  • 将内联汇编改为asm ("imul %0, %0" : "+r"(n)); return n;时编译器报错,修改为asm ("imul %0, %0" : "+r"(n));仍有类似错误。
  • 使用Clang 3.7.1(带-fasm-blocks参数)编译特定代码时,触发语法错误。

需求说明

修复square函数代码,要求不改变基本结构——将n移入寄存器、用mul指令自乘、尽量不使用return语句返回结果,拒绝重写式方案。


修复后的代码

#include <stdio.h>

int square(int n) {
    __asm__ __volatile__ (
        "movl %1, %%eax\n\t"  // 把参数n移入EAX寄存器
        "mull %%eax\n\t"      // EAX自乘,结果低32位保留在EAX中
        : "=a"(n)             // 告知编译器EAX中的结果对应返回值(关联变量n)
        : "r"(n)              // 指定输入参数n可放在任意通用寄存器
        : "%eax"              // 声明EAX会被修改,避免编译器寄存器冲突
    );
    // 无需显式return,x86平台int返回值默认取自EAX,编译器会自动处理
}

int main(void) {
    printf("\nSquare of 4 is %i", square(4));
    return 0;
}

关键修复点

  1. 修正AT&T汇编语法:原代码mov %eax, n操作数顺序颠倒,AT&T语法是「源在前,目的在后」,改为movl %1, %%eax;同时用%%表示实际寄存器,%1对应输入约束的参数n。
  2. 添加约束关联:通过"=a"(n)告诉编译器EAX寄存器的内容是函数返回值(关联到n),"r"(n)让编译器自动分配输入参数的寄存器,避免直接引用变量导致重定位错误。
  3. 遵循调用约定:x86平台C语言返回int类型时,默认将结果存在EAX寄存器,因此无需显式写return语句,符合需求。
  4. 避免编译器优化:添加__volatile__确保汇编块不会被编译器优化掉,保证执行逻辑。

编译原命令即可正常编译运行,无警告和段错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 22:54:19