看看下面的汇编代码:
MOV ESI, DWORD PTR [EBP + C]
MOV ECX, EDI
MOV EAX, EAX
SHR ECX, 2
LEA EDI, DWORD PTR[EBX + 18]
REP MOVS DWORD PTR ES:[EDI], DWORD PTR [ESI]
MOV ECX, EAX
AND ECX, 3
REP MOVS BYTE PTR ES:[EDI], BYTE PTR[ESI]我得到代码摘录的那本书将第一个REP MOVS解释为复制超过4个字节的块,第二个REP MOVS复制剩余的2个字节的块(如果存在)。
REP MOVS指令是如何工作的?根据MSDN的说法,“指令的前缀可以是REP,以将操作重复ecx寄存器指定的次数。”这不就是一遍又一遍地重复相同的操作吗?
发布于 2015-01-07 02:35:02
发布于 2017-05-08 18:23:27
关于语法的简短解释
在汇编代码级别,允许两种形式的指令:“显式操作数”形式和“无操作数”形式。显式操作数形式允许使用符号显式指定存储器的源地址和目标地址。提供此显式操作数表单是为了提供文档;但是,请注意,此表单提供的文档可能具有误导性。也就是说,符号不必指定正确的源地址和目标地址。源地址始终由DS:(RSI/ESI/SI)指定,目标地址始终由ES:(RDI/EDI/DI)寄存器指定,这些寄存器必须在执行movsb指令之前正确加载。这就是我对英特尔在这个问题上的官方立场的理解。
关于语法的长篇解释
REP MOVS DWORD PTR ES:[EDI], DWORD PTR [ESI]是REP MOVSD的同义词;以及
REP MOVS BYTE PTR ES:[EDI], BYTE PTR [ESI]是REP MOVSB的同义词。
根据数据大小,有以下MOVS命令:
中提供
MOVS命令将数据从DS:(SI/ESI/RSI)复制到ES:(DI/EDI/RDI) - SI/DI寄存器的大小取决于您当前的模式-16位、32位或64位。它还增加(减少) SI和DI寄存器(根据D标志,设置CLD以增加寄存器)。
MOVS命令不能使用SI/DI以外的其他寄存器,因此没有必要指定它们。
如果MOVS命令的前缀是REP,则重复复制CX(ECX/RCX)字节数,减少CX,因此在结束时CX变为零。
关于相对性能的解释
自从1993年第一台奔腾CPU问世以来,英特尔就开始让简单的命令执行得更快,让复杂的命令(如REP MOVS)执行得更慢。因此,REP MOVS变得非常慢,没有理由在基于P5微体系结构的奔腾CPU中使用它(1993-1997)。
与P5微体系结构并行,英特尔开发了P6微体系结构,它决定重新访问REP MOVS,并自1996年起实现了使REP MOVS再次快速的“快速字符串”功能。
2013年,英特尔决定再次访问REP MOVS,并实现了CPUID ERMSB (增强的REP MOVSB)位,该位应该表示CPU以快速高效的方式实现了字节大小的移动和存储指令(movsb,stosb)。在实践中,它仅适用于256字节或更大的大块,并且仅当满足某些条件时才是快速的:
源地址和目标地址都必须与16字节的边界对齐(对于常春藤桥处理器,建议使用此边界大小,在较新的情况下,边界可能更大,最多64字节的Cannonlake);
请参阅英特尔优化手册3.7.6增强型REP MOVSB和STOSB操作(ERMSB) http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-optimization-manual.pdf一节
REP MOVS指令在小块上非常慢,因为启动成本大约是35个周期。如果您在循环中执行简单的MOV EAX (或类似的操作),则没有启动成本,并且您可以在这35个周期中复制大量数据。
请注意,ERMSB为REP MOVSB产生最佳结果,而不是REP MOVSD (MOVSQ)。所有的REP MOVS指令都变得更快了,但REP MOVSB是ERMSB中最快的。这与旧处理器(2013年之前)形成对比,在旧处理器中,可用的最大MOVS大小(64位上的MOVSQ,32位上的MOVSD )可产生最快的结果。
因此,您所显示的代码对于具有ERMSB的处理器来说并不是最优的,因为只有MOVSB是快速的,而不是MOVSD,尽管差别不是那么大,而且单个REP MOVSB应该足够了-它只会产生一次启动成本,而不是第一个REP MOVSD和第二个REP MOVSB的启动成本。
但是,对于没有ERMBS的处理器,您的代码是可以的,除了1993年发布的基于P5的奔腾处理器,在该处理器中,简单的MOV复制(或在循环中使用更大的x87寄存器)会更快。您给出的代码在非常老的处理器上也会有最好的结果,比如1985年发布的80386。
https://stackoverflow.com/questions/27804852
复制相似问题