我正在学习x86上的汇编语言并遇到问题,接下来会更快,为什么?
ADD AX, 100
ADD AX, BX
书中的答案是第二个,但我认为第二个需要先读取一个寄存器,第一个可以直接添加。那么有人可以告诉我答案吗?
答案 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
进行编码。
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
的编码保持不变:
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。