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

如何使用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函数设置断点:

    1. 启动GDB:gdb ./facto
    2. 设置断点:break fact
    3. 运行程序:run
      程序会停在fact函数入口,再用nexti或stepi单步执行汇编指令。
  • 验证调试信息生成情况
    检查编译后的文件是否包含调试信息:

    • 检查汇编生成的.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 on
    

    step-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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 08:45:32