ESI 和 EDI 寄存器的用途?

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

我知道它们是用来做字符串运算的。

有人能举个例子吗?

245453 次浏览

有一些操作可以用 DI/SI (或者它们的扩展对应物,如果你没有在1985年学过 ASM 的话)进行 只有。其中包括

REP STOSB
REP MOVSB
REP SCASB

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

以防你想知道: 根据你设置的操作,重复存储可以是一些简单的事情,比如把值0打到一个大的连续内存块中; 我认为,MOVSB 用于从一个缓冲区(好吧,任何一组字节)复制数据到另一个缓冲区; SCASB 用于寻找符合某些搜索条件的字节(我不确定它是否只搜索相等,或什么 & nash; 你可以查找它:)

这就是那些规定的大部分作用。

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

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

除了在其他答案中提到的字符串运算(MOVS/INS/STOS/CMPS/SCASB/W/D/Q 等) ,我想补充的是,还有更多的“现代”x86汇编指令隐含地使用了至少 EDI/RDI:

SSE2 MASKMOVDQU(以及即将发布的 AVX VMASKMOVDQU)指令有选择地将 XMM 寄存器中的字节写入 EDI/RDI 指向的内存。

SI = 源索引
DI = 目的地索引

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

movsb  es:di, ds:si

SI 和 DI 也可以用作通用的索引寄存器

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


虽然我不记得我是在哪里看到它的,但是 这个证实了大部分,而 这个(幻灯片17)证实了其他的:

AX = 蓄电池
双字累加器
CX = 计数器
基寄存器

它们看起来像通用寄存器,但是有许多指令(意外地?)含蓄地使用其中之一,但是使用哪一个呢。

除了用于大规模操作的寄存器之外,它们对于通过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位调用约定,我不确定这些寄存器是否被调用保留。