GDB单步执行后寄存器不会自动刷新,需手动info registers或用display持续监控;寄存器名依架构而异,如x86-64用$rax、ARM64用$x0,错则报“No symbol”;print加格式符(/x、/t)可轻量查值。

单步执行时寄存器不会自动刷新显示,必须手动触发查看,否则你看到的还是上一步的旧值。
单步后不手动查寄存器,就等于没看
很多人在 step 或 next 后直接敲 info registers,却发现值没变——其实不是没变,是调试器没强制刷新显示。GDB 不会在每次单步后自动 dump 寄存器,这是设计使然,不是 bug。
-
step和next只推进 PC($rip或$pc),其他寄存器是否变化取决于指令本身,GDB 不做推测性刷新 - 若刚执行完
mov %rax, %rbx,%rbx已更新,但你不输命令,GDB 就不会告诉你 - 寄存器视图是“快照”,不是“实时仪表盘”
推荐组合:用 display 持续监控关键寄存器
与其每次单步后都手敲 info registers rax rbx rip,不如用 display 让 GDB 自动在每次停顿时打印指定寄存器:
-
display /x $rax—— 十六进制显示$rax,每次停顿时自动输出 -
display /i $rip—— 显示当前指令(含地址),比只看数值更直观 -
undisplay可清空所有 display 项;info display查看当前有哪些 - 注意:
display输出会混在命令回显里,别误以为是错误信息
快速验证某条指令是否改了寄存器,用 print + 格式控制
临时查一两个寄存器,比 info registers 更轻量:
-
print $rsp—— 默认十进制,适合看栈指针偏移量 -
print/x $rdi—— 函数参数常用,十六进制更贴近调用约定 -
print/t $flags—— 查标志寄存器(如$eflags或$rflags)时用二进制看 SF/ZF/CF 位 - 别用
print $rax看地址值——它可能被解释成符号(比如函数名),加/x强制转为原始数值
容易忽略的细节:不同架构寄存器名大小写和前缀不一致
你在 x86_64 上用 $rax,但在 ARM64 的 GDB 里得用 $x0;32 位 x86 是 $eax,不是 $rax。编译目标平台决定寄存器名:
- 确认当前调试的是什么架构:
show architecture或看file输出里的 “PE (x86-64)” 类提示 - 寄存器名错一个字母(比如
$rax写成$raxx)会报No symbol "$raxx" in current context.,不是语法错,是查无此寄存器 - 某些精简版 GDB(如嵌入式交叉工具链附带的)可能不支持
$前缀,得用print rax而非print $rax
真正卡住你的往往不是“怎么查”,而是“查完没注意值已经变了但没对应到指令上”——单步后立刻盯住 $rip 和你关心的源/目标寄存器,比记住所有命令更重要。











