ESI 和 EDI 寄存器的用途?

Posted

技术标签:

【中文标题】ESI 和 EDI 寄存器的用途?【英文标题】:Purpose of ESI & EDI registers? 【发布时间】:2010-12-23 19:14:00 【问题描述】:

汇编程序中EDI和ESI寄存器的实际用途和用途是什么?

我知道它们用于一件事的字符串操作。

谁能举个例子?

【问题讨论】:

看看这个:swansontec.com/sregisters.html 【参考方案1】:

SI = 源索引DI = 目标索引

正如其他人所指出的,它们对字符串指令有特殊用途。对于实模式编程,ES 段寄存器必须与DIDSSI 一起使用,如

movsb  es:di, ds:si

SI 和 DI 也可以用作通用索引寄存器。比如C源代码

srcp [srcidx++] = argv [j];

编译成

8B550C         mov    edx,[ebp+0C]
8B0C9A         mov    ecx,[edx+4*ebx]
894CBDAC       mov    [ebp+4*edi-54],ecx
47             inc    edi

其中ebp+12 包含argvebxjedi 包含srcidx。注意第三条指令使用edi 乘以4 并添加ebp 偏移0x54(srcp 的位置);地址周围的括号表示间接。


虽然我不记得我在哪里看到的,但this 确认了大部分内容,this(幻灯片 17)其他人:

AX = 累加器DX = 双字累加器CX = 计数器BX = 基址寄存器

它们看起来像通用寄存器,但有许多指令(出乎意料?)使用其中的一个——但哪一个?——隐式使用。

【讨论】:

【参考方案2】:

有一些操作只能使用 DI/SI(或它们的扩展对应物,如果您在 1985 年没有学习 ASM)。其中有

REP STOSB
REP MOVSB
REP SCASB

分别是重复(=大量)存储、加载和扫描的操作。您所做的是设置 SI 和/或 DI 指向一个或两个操作数,也许在 CX 中计数,然后让'er rip。这些是一次处理一堆字节的操作,它们使 CPU 处于自动状态。因为您没有显式地编写循环代码,所以它们的工作效率(通常)比手动编码的循环更有效。

以防万一您想知道:根据您设置操作的方式,重复存储可能很简单,例如将值 0 插入一个大的连续内存块;我认为,MOVSB 用于将数据从一个缓冲区(嗯,任何一串字节)复制到另一个缓冲区;并且 SCASB 用于查找与某些搜索条件匹配的字节(我不确定它是否仅在相等性上进行搜索,或者什么 - 你可以查一下 :))

这就是这些 regs 的大部分用途。

【讨论】:

过去的优化提示:rep stoswrep stosb 快很多,所以如果复制两个和两个字节符合你的要求'重新尝试做,在您手动优化的 16 位 x86 汇编代码中使用它...【参考方案3】:

像 MOVSB 和 MOVSW 这样的操作码可以有效地将数据从 ESI 指向的内存复制到 EDI 指向的内存。因此,

mov esi, source_address
mov edi, destination_address
mov ecx, byte_count
cld
rep movsb ; fast!

【讨论】:

【参考方案4】:

除了其他答案中提到的字符串操作(MOVS/INS/STOS/CMPS/SCASB/W/D/Q 等)之外,我想补充一点,还有更多“现代”x86 汇编指令至少隐式使用 EDI/RDI:

SSE2 MASKMOVDQU(以及即将推出的 AVX VMASKMOVDQU)指令选择性地将字节从 XMM 寄存器写入 EDI/RDI 指向的内存。

【讨论】:

【参考方案5】:

除了用于批量操作的寄存器之外,它们还有助于通过 32 位调用约定中的函数调用(调用保留)来保留它们的属性。 ESI、EDI、EBX、EBP、ESP 是呼叫保留的,而 EAX、ECX 和 EDX 不是呼叫保留的。调用保留寄存器受 C 库函数的尊重,并且它们的值通过 C 库函数调用保持不变。

Jeff Duntemann 在他的汇编语言书中有一个用于打印命令行参数的示例汇编代码。该代码使用 esi 和 edi 来存储计数器,因为它们不会被 C 库函数 printf 更改。对于 eax、ecx、edx 等其他寄存器,不能保证它们不会被 C 库函数使用。

https://www.amazon.com/Assembly-Language-Step-Step-Programming/dp/0470497025

请参阅第 12.8 节 C 如何查看命令行参数。

请注意,64 位调用约定与 32 位调用约定不同,我不确定这些寄存器是否保留调用。

【讨论】:

我从来没有听说过“神圣”用来描述大多数人所说的“易失性”/“非易失性”,或者“被调用者保存”与“调用者保存”。我喜欢“call-preserved”/“call-clobbered”,因为这并不意味着它们实际上被保存在任何地方。无论如何,ESI/RSI 和 EDI/RDI 在 x86-64 System V ABI 中不会保留调用。 另外,您忘记在常见的 32 位调用约定中将 EBP 和 ESP 列为调用保留。 无论如何,这是一个很好的观点。在实际代码中,您更有可能出于调用约定的原因选择 EDI/ESI,而不是因为它们对于任何指令都是特殊的。 我喜欢保留通话。我已经用同样的方法更新了答案。感谢您的评论。

以上是关于ESI 和 EDI 寄存器的用途?的主要内容,如果未能解决你的问题,请参考以下文章

汇编之 eax, ebx, ecx, edx, esi, edi, ebp, esp??

汇编初识

160CrackMe~001

寄存器小记

实模式与保护模式详解一:寄存器

汇编指令和寄存器