【发布时间】:2011-04-18 15:29:33
【问题描述】:
我最近偶然发现了以下汇编指令序列:
rep stos dword ptr [edi]
【问题讨论】:
我最近偶然发现了以下汇编指令序列:
rep stos dword ptr [edi]
【问题讨论】:
对于ecx 重复,将eax 的内容存储到edi 指向的位置,每次递增或递减edi(取决于方向标志)4 个字节。通常,这用于memset 类型的操作。
通常,该指令只是写成rep stosd。经验丰富的汇编编码人员只要看到这些就知道上面提到的所有细节。 :-)
ETA 完整性(感谢 PhiS):每次迭代,ecx 减 1,当达到 0 时循环停止。对于stos,您唯一会观察到的是ecx 在最后被清除。但是,对于scas 等,在使用repz/repnz 前缀的情况下,如果在耗尽ecx bytes/words/whatevers 之前停止操作,ecx 可以大于零。
在你问之前,scas 用于实现strchr 类型的操作。 :-P
【讨论】:
memset 的 32 位版本,其中要设置的内容是 32 位数量(与 memset 不同,其中要设置的内容是 char )。 ecx 指定要设置的双字数(而不是字节数)。
stosd,dword 中的各个字节可以有不同的内容。
Empty array:
char buff[256] = { };
776 1c5: 48 8d 95 e0 fc ff ff lea -0x320(%rbp),%rdx
777 1cc: b8 00 00 00 00 mov $0x0,%eax
778 1d1: b9 20 00 00 00 mov $0x20,%ecx
779 1d6: 48 89 d7 mov %rdx,%rdi
780 1d9: f3 48 ab **rep stos %rax,%es:(%rdi)**
【讨论】:
rep stosq,但肯定够接近。 (用 AT&T 语法反汇编)。这看起来像是未优化的 gcc 输出;在某些情况下,它将内联rep stos,而不是调用memset,即使进行了优化。显然,优化后的代码不会花费 2 条单独的指令将指针指向 RDI,并且会使用xor %eax,%eax 将 RAX 归零。 (如果它没有完全优化掉数组。)
mov $0, %eax 到零 RAX 一样,没有异或零窥孔优化(gcc 仅在 -O2 查找,这启用了 @987654330 @)。对于 XOR,使用额外的 REX 前缀会更糟糕,就像使用 MOV 一样。 What is the best way to set a register to zero in x86 assembly: xor, mov or and?