惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hacker News: Front Page
P
Palo Alto Networks Blog
T
ThreatConnect
Apple Machine Learning Research
Apple Machine Learning Research
博客园_首页
T
True Tiger Recordings
P
Privacy & Cybersecurity Law Blog
B
Blog
IT之家
IT之家
Last Week in AI
Last Week in AI
F
Full Disclosure
Hacker News: Ask HN
Hacker News: Ask HN
C
Comments on: Blog
Microsoft Azure Blog
Microsoft Azure Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Microsoft Security Blog
Microsoft Security Blog
博客园 - 【当耐特】
N
News and Events Feed by Topic
NISL@THU
NISL@THU
腾讯CDC
雷峰网
雷峰网
Security Latest
Security Latest
李成银的技术随笔
M
Microsoft Research Blog - Microsoft Research
L
LangChain Blog
L
Lohrmann on Cybersecurity
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Check Point Blog
Y
Y Combinator Blog
Recent Announcements
Recent Announcements
博客园 - Franky
N
News | PayPal Newsroom
V
V2EX
A
About on SuperTechFans
The Register - Security
The Register - Security
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Google Online Security Blog
Google Online Security Blog
MyScale Blog
MyScale Blog
Cisco Talos Blog
Cisco Talos Blog
Vercel News
Vercel News
WordPress大学
WordPress大学
C
Cyber Attacks, Cyber Crime and Cyber Security
The Hacker News
The Hacker News
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
爱范儿
爱范儿
A
Arctic Wolf
L
LINUX DO - 最新话题
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

博客园 - PKICA

汇编语言语法详解 gdb-pwndbg的安装与使用指南 gdb调试插件gef C语言thread_local linux系统readelf命令使用指南 gcore转储进程内存 gdb查看命令 RGB与YUV颜色编码的区别 Rust原子类型 C++ STL求两个集合交集差集 gdb调试集锦 ubuntu24.0.4使用root用户登录 ubuntu24.0.4输入密码后跳回登录界面 AI内存压缩技术TurboQuant及存疑 ubuntu切换到指定内核版本 在没有顶级科技大佬直接背书的情况下deepseek为啥能够异军突起? HuggingFace和deepseek的关系 当前主流AI大模型 Rust写时克隆Cow系列2
gdb汇编调试
PKICA · 2026-04-15 · via 博客园 - PKICA

当你进入汇编级别(Assembly level)的调试时,通常是因为 C 源代码已经无法解释当前的现象(比如你遇到的栈被踩烂、寄存器污染或 ??() 这种断层)。

在 GDB 中,从“源码级”切换到“汇编级”调试,主要依靠以下三板斧:

1. 开启汇编视觉模式(最推荐)

不要一行行输入命令,直接进入 GDB 的 TUI (Text User Interface) 模式,让你边看代码边看汇编。

  • layout split: 同时显示源代码和汇编代码。

  • layout regs: 显示寄存器状态和汇编代码。

  • focus asm: 将键盘焦点切换到汇编窗口,方便翻页。

  • layout next:切换到下一个布局方案
  • layout prev:切换到上一个布局方案

小技巧:在 TUI 模式下,当前执行的那一行汇编会被高亮。配合 stepi 极其直观。

在 GDB 的 TUI(文本用户界面)模式中,想要退出 layout asm 或关闭图形窗口回到纯命令行模式,有几种常用的方式:

1). 彻底退出 TUI 模式

如果你想关闭所有窗口(汇编、寄存器等),回到最原始的命令行界面:

  • 快捷键: Ctrl + X 紧接着按 A

    这是一个开关操作:如果当前在 TUI 模式,按它可以退出;如果在命令行模式,按它可以重新进入上一次的布局。

2). 切换回源码布局

如果你只是不想看汇编了,想切回 C/C++ 源码界面:

  • 命令: layout src

    注意:这需要你的程序在编译时带了 -g 选项,否则窗口会显示找不到源码。

常见问题:界面乱了怎么办?

在 TUI 模式下,如果程序运行输出(printf)污染了汇编窗口,导致界面字符错位,不需要退出,只需输入:

  • refresh 或者按下 Ctrl + L

    这会重新绘制屏幕,修复显示乱码。

提个醒: 如果你发现按方向键无法查看历史命令,而是移动了汇编窗口,可以输入 focus cmd 将输入焦点切回命令行窗口。

2. 核心指令:执行控制

在汇编调试中,传统的 n (next) 和 s (step) 颗粒度太粗了,你需要:

  • stepi (或 si): 执行一条机器指令。如果这行指令是 call,它会跳进函数内部。

  • nexti (或 ni): 执行一条机器指令。如果这行指令是 call,它会直接执行完该函数,停在下一条指令。

  • until *0x地址: 运行到指定的内存地址处停下。

3. 观察寄存器与内存

既然是汇编,寄存器就是你的变量。

  • info registers (或 i r): 查看所有通用寄存器的值。

  • p $rax: 打印特定寄存器(如 rax)的值。在 64 位系统中,通常 rax 存放函数返回值。

  • display /i $pc: 每次停下时,自动显示下一条要执行的汇编指令。

  • x/gx $rsp: 检查栈顶。对于调试递归引起的 ??(),这是看谁把返回地址改了的唯一方法。

4. 关键场景:如何通过汇编定位递归崩溃?

当你遇到 ??()bt 失效时,在汇编级你可以这样排查:

A. 查看当前的指令指针 (RIP)

(gdb) p /x $rip

如果 rip 指向了一个不属于代码段的地址(比如 0x0 或一个巨大的随机数),说明你的程序执行了 ret 指令,但从栈上弹出的返回地址是错的。

B. 检查函数序言 (Prologue)

使用 disassemble 查看当前函数的开头:

(gdb) disassemble my_func

你会看到类似这样的指令:

push   %rbp
mov    %rsp,%rbp
sub    $0x40,%rsp  <-- 这里在分配栈空间

如果递归太深,执行到 sub $0x40,%rsp 后,栈指针 $rsp 可能会越界进入不可写的内存页,直接触发 SIGSEGV

5. 实用反汇编技巧

  • disassemble /m: 将汇编代码和源代码穿插显示(非常适合理解 C 代码如何转译成机器码)。

  • disassemble /r: 显示原始的十六进制机器码(Opcode)。

  • set disassembly-flavor intel: 如果你看补惯 AT&T 格式(mov %src, %dest),可以切换到 Intel 格式(mov dest, src)。

总结

如递归问题,在汇编层级看其实就是:

  • 大量的 push %rbp 将旧的帧指针压栈。

  • 不断的 call 指令跳转回函数开头。

  • 最终 $rsp 撞到了内存管理的墙(Guard Page)。

进阶挑战: 下次在 GDB 里,试着在递归崩溃前执行 x/5i $pc,看看崩溃那一刻 CPU 到底是在执行 push(压栈失败)还是 mov(访问非法地址)。

参考资料: