如何使用GDB调试NASM编写的x86汇编代码?
无法用GDB调试x86汇编代码的排查与解决
以下是针对你的问题的具体解决线索:
修正C代码中的函数声明
你的main.c里extern int fact();是旧式无参数函数声明,不符合C99及后续标准,且与汇编函数的实际行为不匹配:- 汇编中
fact通过rdi接收参数(x86-64 System V调用约定) - 函数返回值存在
rax中,对应C的size_t类型
把声明修改为:
extern size_t fact(size_t n);错误声明可能导致GCC优化时跳过函数调用的调试信息关联,甚至引发参数传递异常。
- 汇编中
规范GDB断点设置方式
不要仅依赖step命令直接步入,手动给fact函数设置断点:- 启动GDB:
gdb ./facto - 设置断点:
break fact - 运行程序:
run
程序会停在fact函数入口,再用nexti或stepi单步执行汇编指令。
- 启动GDB:
验证调试信息生成情况
检查编译后的文件是否包含调试信息:- 检查汇编生成的
.o文件:readelf -S facto.o | grep -i dwarf,应能看到.debug_*相关段 - 检查最终可执行文件:
readelf -S facto | grep -i dwarf,确认调试段被保留
- 检查汇编生成的
调整NASM调试信息选项
尝试将NASM的调试标志从-gdwarf改为-gdwarf2或-gdwarf3,部分环境下新版NASM默认的-gdwarf版本可能与GDB兼容性存在问题:
修改Makefile中的编译规则:$(BIN): $(ASM) nasm -f elf64 -gdwarf2 $(ASM) -o $(BIN)优化GDB行为设置
关闭GDB可能跳过函数调用的相关设置:set step-mode on set debug entry-breakpoints onstep-mode on会让GDB即使没有调试信息也会步入函数,而非直接跳过。
附原问题代码:
facto.asm
global fact section .text fact: push rbx mov rcx, rdi xor rax, rax xor rbx, rbx inc rax inc rbx loop: mov rdx, rbx mul rdx inc rbx dec rcx jnz loop pop rbx ret
Makefile
EXE := facto BIN := $(EXE).o ASM := $(EXE).asm SRC := main all: $(EXE) $(BIN): $(ASM) nasm -f elf64 -gdwarf $(ASM) -o $(BIN) $(EXE): $(SRC).c $(BIN) gcc -no-pie -g $(SRC).c $(BIN) -o $(EXE) .PHONY: clean clean: $(RM) *.o $(RM) $(EXE)
main.c
#include <stdio.h> extern int fact(); int main(void) { size_t res = fact(5); printf("%zu\n",res); }
内容的提问来源于stack exchange,提问作者Vladouch
相关产品推荐
相关产品推荐

