ESI和EDI寄存器的用途?

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

我知道他们用于string操作的一件事情。

有人也可以举个例子吗?

有几个操作你只能用DI / SI(或者扩展的对应的,如果你在1985年没有学习ASM的话)。 这些之中

REP STOSB REP MOVSB REP SCASB 

分别是重复(=大量)存储,加载和扫描的操作。 你所做的是将SI和/或DI设置为指向一个或两个操作数,也许把一个计数放在CX中,然后让它呃裂开。 这些是一次处理一堆字节的操作,它们使CPU处于自动状态。 因为你没有明确地编码循环,所以它们比通过手动编码的循环更有效率(通常)。

以防万一你想知道:根据你如何设置操作,重复存储可以是简单的,如将值0打成一个大的连续的内存块; 我认为使用MOVSB将数据从一个缓冲区(以及任何字节串)复制到另一个缓冲区; 和SCASB是用来寻找一个字符匹配一些search标准(我不知道它只是在平等搜寻,或者什么 – 你可以看看:))

这是这些区域大部分的用途。

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

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

 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 mulitplied 4,并增加ebp偏移0x54( srcp的位置); 地址周围的括号表示间接。


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

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

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

像MOVSB和MOVSW这样的操作码能够有效地将ESI指向的内存中的数据复制到EDI指向的内存中。 从而,

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

除了其他答案中提到的string操作(MOVS / INS / STOS / CMPS / SCASB / W / D / Q等)之外,我想补充说的是,还有更多的“现代”x86汇编指令隐含地用于最lessEDI / RDI:

SSE2 MASKMOVDQU (和即将发布的AVX VMASKMOVDQU )指令有select地将字节从XMM寄存器写入EDI / RDI指向的存储器。

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