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

GNU AS Intel语法汇编代码运行无输出,求助排查原因

问题排查与解决方案

先明确一个关键信息:Linux下退出码14对应EFAULT(无效内存地址错误),说明你的程序尝试访问了非法内存区域。结合你用GAS Intel语法编译32位程序、NASM修改后可正常运行的情况,问题基本出在GAS与NASM的Intel语法细节差异上,具体看以下几个核心点:

1. 符号地址引用的语法差异

这是最常见的坑:

  • NASM中直接写符号名就能获取其内存地址,比如mov ecx, msg;
  • 但在GAS的.intel_syntax noprefix模式下,必须用OFFSET关键字来获取符号的地址,正确写法是mov ecx, OFFSET msg。

如果省略OFFSET,GAS会把符号所在位置的字节值加载到寄存器里,而不是内存地址本身——这会导致write这类系统调用收到一个完全无效的指针,直接触发EFAULT错误,也就是你看到的退出码14。

举个对比示例:

NASM 正确写法

global _start

_start:
    mov eax, 4          ; sys_write 调用号
    mov ebx, 1          ; stdout 文件描述符
    mov ecx, msg        ; 字符串地址
    mov edx, msg_len    ; 字符串长度
    int 0x80

    mov eax, 1          ; sys_exit 调用号
    xor ebx, ebx
    int 0x80

msg:
    db "Hello, world!", 0xA
msg_len equ $ - msg

GAS Intel语法 正确写法

.intel_syntax noprefix
.global _start  ; 注意GAS的全局符号声明是点开头的伪指令

_start:
    mov eax, 4
    mov ebx, 1
    mov ecx, OFFSET msg  ; 必须加OFFSET获取地址
    mov edx, OFFSET msg_len
    int 0x80

    mov eax, 1
    xor ebx, ebx
    int 0x80

msg:
    .ascii "Hello, world!\n"
msg_len = . - msg  ; GAS用等号+当前地址.来计算长度

2. 入口点声明的语法差异

NASM用global _start(无点)声明入口点,而GAS必须用.global _start(带点的伪指令)。如果漏写或者写错,链接器可能无法正确识别程序入口,导致运行时出现未知内存访问错误。

3. 快速验证与调试技巧

如果调整上述语法后仍有问题,用strace ./a.out跟踪系统调用:它会显示每个系统调用的参数和返回值,能直接定位到哪个调用传递了无效地址,帮你快速锁定问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:33:10