### 单步执行的原理是什么

**1. 陷阱标志**

在 x86 架构的 CPU 中，有一个特殊的寄存器叫做 **EFLAGS**（在 64 位系统中是 RFLAGS）。这个寄存器中的每一位都代表一个特定的状态或控制标志。其中的第 8 位就是**陷阱标志（TF）**

- **当 TF=0 时**：CPU 正常执行指令，不会触发单步中断
- **当 TF=1 时**：这是单步执行的关键。CPU 在执行完一条指令后，会自动产生一个 **INT 1** 异常（也就是**单步中断**）

**2. 单步执行的原理流程**

当你在调试器中点击“单步”按钮时，幕后会发生以下几个步骤：

1. **调试器设置 TF 标志位：** 调试器通过系统调用或直接操作，将 **EFLAGS 寄存器中的 TF 位设置为 1**
2. **CPU 执行下一条指令：** CPU 继续正常执行程序代码中的下一条指令
3. **CPU 产生 INT 1 异常：** 在这条指令执行完毕后，CPU 检查到 TF 标志位为 1，于是自动停止正常的程序执行流程，并产生一个 **INT 1 异常**
4. **操作系统捕获异常：** 操作系统有一个专门的**中断描述符表（IDT）**。当 INT 1 异常发生时，操作系统会根据 IDT 中预先设置好的入口点，将控制权交给处理 INT 1 异常的程序
5. **调试器接管控制权：** 由于调试器是操作系统中管理被调试进程的组件，它会事先向操作系统注册一个异常处理函数。因此，当 INT 1 异常发生时，**控制权实际上被交给了调试器**
6. **调试器暂停程序：** 调试器在接管控制权后，会暂停被调试程序的执行，并显示当前的程序状态（寄存器值、内存数据等）
7. **等待用户操作：** 此时，程序在调试器中处于暂停状态，等待你进行下一步操作，比如再次单步、查看变量或继续运行

如果你再次点击“单步”，这个循环会重新开始：调试器再次设置 TF，程序执行一条指令，然后控制权再次回到调试器

**3. 特殊情况：`INT 3` 断点**

除了利用 TF 标志位，调试器还有一个常用的单步执行辅助手段，那就是**`INT 3` 指令**

- 当你在某行代码上设置了一个断点（Breakpoint）时，调试器会偷偷地将该行代码的第一个字节替换成 **`0xCC`**
- `0xCC` 对应的汇编指令就是 **`INT 3`**
- 当程序执行到这个位置时，CPU会像处理单步中断一样，产生一个 **INT 3 异常**
- 操作系统将控制权交给调试器，程序暂停，从而实现了“断点”的功能

所以，当调试器在一个断点处暂停后，你点击单步，调试器会先**将 `0xCC` 恢复为原来的指令**，然后**设置 TF 标志位**，让程序执行那条被恢复的指令，最后在指令执行完毕后，再次设置 `0xCC`，等待下一次的断点触发