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
段寄存器必须与DI
和DS
与SI
一起使用,如
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
包含argv
,ebx
为j
,edi
包含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 stosw 比 rep 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 寄存器的用途?的主要内容,如果未能解决你的问题,请参考以下文章