变址寄存器
作者:Vesper Vei
2 分钟阅读
目录
变址寄存器
理解变址寄存器(Index Registers)最好的方式,就是把它们想象成搬运工的“GPS坐标”。 在 x86-64 架构中,RSI 和 RDI 就像是一对搭档:一个负责告诉 CPU “东西在哪”(源),另一个负责告诉 CPU “送到哪去”(目的)。
1. 核心逻辑:源与目的
我们可以通过一张简单的对比表来快速建立直觉:
| 寄存器 | 全称 | 核心角色 | 现实比喻 |
|---|---|---|---|
| RSI | Source Index | 源操作数指针 | “货源地”的地址 |
| RDI | Destination Index | 目的操作数指针 | “收货地”的地址 |
[!NOTE]
现代 x86-64 的变化:在 64 位 Linux 系统中(System V AMD64 ABI),RDI 和 RSI 还有个极其重要的身份——函数参数。
RDI:存储函数的第 1 个参数。
RSI:存储函数的第 2 个参数。
2. 深度融合:C 与汇编的对照实验
为了让你彻底理解,我们来看一个最经典的场景:内存拷贝(Memory Copy)。
C 语言代码
这段代码实现了一个简单的字符拷贝功能:将 src 指向的字符复制到 dest。
void manual_copy(char *dest, const char *src) { *dest = *src; // 把源地址的内容搬到目的地址}对应的汇编代码(x86-64)
当你调用 manual_copy(buffer, message) 时,编译器会这样安排寄存器:
代码段
; 假设进入函数时:; RDI = dest 的地址 (第一个参数); RSI = src 的地址 (第二个参数)
manual_copy: mov al, [rsi] ; 【从源头取货】:把 RSI 指向地址里的 1 字节数据读到 AL 寄存器 mov [rdi], al ; 【送到目的地】:把 AL 里的数据写到 RDI 指向的地址中 ret ; 返回3. 进阶玩法:字符串指令(String Instructions)
之所以叫“变址寄存器”,是因为 x86 专门设计了一些“全自动”指令。比如 movsb (Move String Byte),它会自动利用 RSI 和 RDI。
批量搬运示例
如果我们想一次性搬运 10 个字节:
-
C 语言:
memcpy(dest, src, 10); -
汇编指令:
代码段
lea rsi, [src_buffer] ; RSI = 源缓冲区首地址lea rdi, [dest_buffer] ; RDI = 目标缓冲区首地址mov rcx, 10 ; 计数器设置为 10rep movsb ; 【自动搬运】: ; 1. 把 [RSI] 的东西搬到 [RDI] ; 2. RSI++,RDI++ (自动指向下一个字节) ; 3. 重复执行,直到 RCX 为 0在这里,RSI 和 RDI 的“变址”特性体现得淋漓尽致:它们不仅是地址,还会随着搬运的过程自动增加,就像仓库里自动前进的传送带。
4. 记忆技巧总结
- SI = Start / Source(开始的地方 / 源头)
- DI = Destination / Done(目的地 / 结束的地方)
在逆向分析或者调试代码时,如果你看到
rep movs或者大量的[rsi]/[rdi]操作,你的第一反应应该是:“CPU 正在进行大搬迁!”
你想继续深入了解一下函数调用约定(Calling Convention) 吗?也就是为什么 RDI 是第一个参数,而 RSI 是第二个参数的“潜规则”。
—> RDI作为第一个参数的“潜规则”