常见错误与排障(Troubleshooting)

按"汇编 → 链接 → 运行"三个阶段收录常见报错与对策。报错原文以 GNU binutils 为准(不同版本措辞略有差异,关键是识别模式)。

汇编阶段(as)

报错(模式) 原因 对策
no instruction mnemonic suffix given and no register operands; using default(警告) 指令涉及内存/立即数但没写大小后缀,GAS 套用默认 32 位 显式写后缀:movl $1, (%rax) 而非 mov $1, (%rax)
operand size mismatch 操作数大小不匹配(含内存↔内存这种非法组合) 检查后缀;内存到内存必须经寄存器中转
bad register name 寄存器名写错,或混入了中文标点(如 %eax; 检查全角符号,代码只用 ASCII 标点
no such instruction 拼写错误,或指令属于未开启的扩展 模块十七;用 gcc -mavx2 -c 等开启扩展
unknown pseudo-op 伪指令拼写错误或版本不支持 核对伪指令表(模块二
junk at end of line 行尾有多余内容(多余的逗号/操作数) 检查操作数个数与分隔
expecting operand 缺少操作数 补全
no such architecture .arch 值不受支持(x86 64 位模式支持有限) 改用 gcc 的 -m 选项,见模块二
undefined symbol / 标号未定义 引用了不存在的标号 检查标号拼写、1f/1b 方向、跨文件引用需 .globl
cannot represent relocation / 立即数超范围 立即数超过 32 位(非 mov) movabsq 或寄存器中转

链接阶段(ld / gcc 链接)

报错(模式) 原因 对策
undefined reference to 'foo' 符号在目标文件/库中不存在 检查 .globl 声明、拼写、是否忘了把 .o 传给链接器
relocation truncated to fit: R_X86_64_32S 32 位符号扩展位移放不下(符号距离/地址超出 ±2GB) 改用 RIP 相对寻址、movabsq+寄存器间接、或调整代码布局
missing .note.GNU-stack section implies executable stack(警告) 汇编源没有栈权限标记 .section .note.GNU-stack,"",@progbits模块二
无法找到项目符号 _start(警告,缺省入口 0x401000) 没有定义 _start,链接器随便指了个入口——程序基本无法运行 定义 _start 或用 ld -e 入口名
链接 libc 时报 undefined reference to 'printf' 用裸 ld 链接却调用了 libc 改用 gcc 驱动 链接,或手动 -lc + 动态链接器路径

运行阶段

症状 常见原因 排查
Segmentation fault 入口错误、参数寄存器搞错、忘了 lea(把数据当指针)、callee-saved 未保存、栈未对齐后用了 movaps gdbrunbtx/i $pc 定位(模块十四
Illegal instruction (SIGILL) 使用了 CPU 不支持的指令 / OS 未启用 XCR0 状态 模块十五 的检测流程
SIGBUS 错对齐的内存访问(如 movaps 访问非 16 字节对齐地址) 检查 .align/.p2align模块十
SIGFPE 整数除零(div/idiv 除数为 0,或商溢出) 检查除数寄存器是否被清错
程序"什么都没干"就退出 退出码只取低 8 位;或没有 exit 直接跑了 .text 后面的数据 检查退出路径(模块七
结果莫名被改动 子寄存器写规则(写 32 位清高 32 位)、%rdx 除法残留 模块一模块四

快速定位流程图

汇编不通过 ──► 按 as 报错行号查上表
链接不通过 ──► undefined reference → 查符号/globl
            └► relocation truncated → 查寻址方式
运行崩溃   ──► gdb ./prog
               run
               bt                # 看调用栈
               x/i $pc           # 看崩溃指令
               info registers    # 看寄存器值
               strace ./prog     # 看最后做了什么系统调用

配套工具一览

工具 用途
as -a 列出汇编清单(源码+机器码对照)
objdump -dr 反汇编 + 重定位信息(查 relocation 问题)
readelf -hS / readelf -s ELF 节区 / 符号表
nm 快速查看符号定义与缺失
strace 跟踪系统调用与信号
gdb 寄存器/内存/单步(模块十四);core dump、反向调试、多线程等进阶见模块十九

更多防错要点见总览的"常见陷阱"一节。