哪种汇编语言语句执行得更快?

时间:2015-01-11 15:03:36

标签: assembly x86

我正在学习x86上的汇编语言并遇到问题,接下来会更快,为什么?

ADD AX, 100 

ADD AX, BX  

书中的答案是第二个,但我认为第二个需要先读取一个寄存器,第一个可以直接添加。那么有人可以告诉我答案吗?

5 个答案:

答案 0 :(得分:1)

这取决于上下文(程序的其余部分)。

第二条指令引入了数据依赖关系,如果你只需要从主内存加载BX,你可能需要拖延很长时间。另一方面,第一条指令增加了数据占用空间,因此在指令高速缓存中需要更多空间来编码立即值,如果它足以在某些性能中引起一些额外的失误,这可能是至关重要的 - 关键循环。

最重要的是,今天有些CPU可以执行寄存器复制而无需执行任何操作(仅使用寄存器重命名),因此它还取决于您使用的确切微架构。

我的建议是 - 找另一本书,一本不会告诉你会发生什么的书。此外,使用AX和BX意味着它相当古老......

答案 1 :(得分:1)

答案取决于CPU的实际实现,具体取决于它的设计时间。较旧的CPU将具有与新的不同的时序。

对于现代CPU,通常这些速度相同,因为CPU设计人员在常见情况下快速制作基本指令时投入了大量资源。

即便如此,人们可以构建ADD AX,BX速度更快的情况(最后一条指令完全在缓存行中,下一条缓存线即使使用预取也没有从内存到达)和一些其中ADD AX ,100将更快(BX由一些早期指令提供,需要很长时间才能完成)。

对于这对特定的指令,我不会花太多时间担心它。最好用你认为合理的选择来编写你的代码(float-add几乎总是慢于整数加,因为它要复杂得多)。 [一旦你写了相当数量的汇编代码,这很容易]。运行代码后,测量性能并在必要时进行优化。通常需要优化的地方是一个惊喜。

答案 2 :(得分:1)

在现代处理器中,性能没有差异。如果将立即数从100更改为128(或更大),则可能存在显着差异。我知道这听起来很奇怪。

有几家x86处理器制造商(英特尔,AMD,维亚),每家都有多代处理器设计(微架构)。您的问题一般无法回答,因为答案取决于微架构。对于英特尔来说,这类问题的一个很好的资源是

Intel® 64 and IA-32 Architectures Optimization Reference Manual

现代高性能CPU是复杂的机器。对于大多数代码,您不必担心这种详细程度,您可以使用高级语言编写,使用优化编译器,并且开心。当您的代码性能至关重要时,您可能必须关注这些细节。如果是这种情况,那么您需要了解您所针对的特定微架构,处理器所处的模式,以及可能的直接实际值(惊喜!)。与您的问题相关的是处理器是否在

问题ADD AX,100中的指令是将16位立即数(可以编码为带符号的8位立即数)添加到16位寄存器。与使用不符合8位的有符号立即数相比,可以使用不同的操作码来完成。我使用以下网站收集这些说明:

https://defuse.ca/online-x86-assembler.htm#disassembly

请注意,将ADD 8位带符号立即数AX编码为ADD可以使用与编码不同的操作码和使用16位立即签名的0: 83 c0 64 add ax,100 3: 05 80 00 add ax,128 进行编码。

16位(实模式,虚拟8086模式)

ADD

你可能想知道,那又怎样?它是相同的字节数...但它还有更多。在32位模式下,某些指令编码在实模式下被解释为16位ADD,现在被解释为32位operand size override prefix byte。为了在32位模式下编码16位加法,x86需要ADD,0x66。 8位0: 66 83 c0 64 add ax,100 4: 66 05 80 00 add ax,128 8: 83 c0 64 add eax,100 b: 05 80 00 00 00 add eax,128 的编码保持不变:

32位或x86-64(长模式)

length changing prefixes (LCP)

这是重要的事情,请注意0x05操作码后跟两个字节(当存在0x66前缀时)或四个字节(默认情况下,当0x66不存在时)。这会对指令预解码器造成严重破坏,该解码器试图一次解码许多指令,并且因为x86指令可以是1到15个字节的任何位置,所以它基于操作码对默认大小进行假设。具有16位立即数的指令上的0x66前缀会改变指令的总长度...这被称为{{1}}并且可以在解码器中引入三到六个周期停顿 ,取决于微架构,这可能很重要。

在英特尔优化手册中搜索以下规则以获取更多信息

  

汇编/编译器编码规则21 。 (MH影响,MH普遍性)偏好   使用imm8或imm32值而不是imm16值生成代码。

  

汇编/编译器编码规则27 。 (M影响,MH普遍性)避免   使用前缀来改变立即和位移的大小。

答案 3 :(得分:0)

在较旧的80X86 CPU中,需要从内存中读取操作数的立即值,而寄存器操作数则在指令本身中进行编码,该指令已经被“读取”。所以

add ax, bx

是一条指令;阅读之后,所需要的一切都是在内部" CPU,可以立即处理。

指令

add ax, 100

被解析为add ax, ?,因此CPU需要先从内存中读取下一个单词才能继续。

对于新的CPU来说已不再适用,但OP提到的书(其标题和出版日期未提及)可能已经足够老了。

答案 4 :(得分:0)

回到8086/8088足够远,并且斧头,100 [ax]比添加ax,100更快。我不确定80286。