ESI和EDI寄存器的用途?

Ton*_*ion 115 x86 assembly

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

我知道它们只用于字符串操作.

有人也可以举个例子吗?

wal*_*lyk 78

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

正如其他人所指出的,它们具有字符串指令的特殊用途.对于实模式编程,ES段寄存器必须使用DI,并DSSI作为

movsb  es:di, ds:si
Run Code Online (Sandbox Code Playgroud)

SI和DI也可用作通用索引寄存器.例如,C源代码

srcp [srcidx++] = argv [j];
Run Code Online (Sandbox Code Playgroud)

汇编成

8B550C         mov    edx,[ebp+0C]
8B0C9A         mov    ecx,[edx+4*ebx]
894CBDAC       mov    [ebp+4*edi-54],ecx
47             inc    edi
Run Code Online (Sandbox Code Playgroud)

其中ebp+12含有argv, ebxjedi拥有srcidx.注意第三条指令使用edimulitplied by 4并将ebp偏移量加上0x54(位置srcp); 地址周围的括号表示间接.


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

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

它们看起来像通用寄存器,但是有许多指令(意外地?)使用其中一个 - 但是哪一个? - 明显地.


Car*_*icz 74

有一些操作只能用DI/SI(或扩展的对应物,如果你在1985年没有学习ASM).其中有

REP STOSB
REP MOVSB
REP SCASB
Run Code Online (Sandbox Code Playgroud)

它们分别是重复(=质量)存储,加载和扫描的操作.你做的是你设置SI和/或DI指向一个或两个操作数,也许在CX中计数然后让我们翻录.这些操作一次只能处理一堆字节,它们可以自动处理CPU.因为你没有明确地编码循环,所以它们(通常)比手动编码循环更有效.

万一你想知道:根据你设置操作的方式,重复存储可以很简单,比如将值0打到一个大的连续内存块中; 我认为,MOVSB用于将数据从一个缓冲区(以及任何字节串)复制到另一个缓冲区; 和SCASB用于查找匹配某些搜索条件的字节(我不确定它是否只搜索相等,或者是什么 - 你可以查找:))

这是那些注册表的大部分内容.

  • 过去的优化提示:*rep stosw*比*rep stosb*快很多,所以如果复制两个和两个字节符合你想要做的,那么在你手动优化的16位x86汇编中使用它码... (6认同)

cat*_*ood 33

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

mov esi, source_address
mov edi, destination_address
mov ecx, byte_count
cld
rep movsb ; fast!
Run Code Online (Sandbox Code Playgroud)


Phi*_*hiS 12

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

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


Jay*_*put 6

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