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
一起使用,将SI
与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
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位调用约定不同,我不确定这些寄存器是否被调用保存。