ChatGPT解决这个技术问题 Extra ChatGPT

ESI 和 EDI 寄存器的用途?

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

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

有人也可以举个例子吗?


D
Daniel S.

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 的位置);地址周围的括号表示间接。

这个

这个

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

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


C
Carl Smotricz

有一些操作只能使用 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 汇编代码中使用它...
N
Nils Pipenbrinck

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

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

P
PhiS

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

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


J
Jay Rajput

除了用于批量操作的寄存器之外,它们还有助于通过 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,而不是因为它们对于任何指令都是特殊的。
我喜欢电话保留。我已经用同样的方法更新了答案。感谢您的评论。