Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 汇编中的指令成本激增_Performance_Assembly_X86 - Fatal编程技术网

Performance 汇编中的指令成本激增

Performance 汇编中的指令成本激增,performance,assembly,x86,Performance,Assembly,X86,我一直对组装过程中的跳跃成本感到好奇 cmp ecx, edx je SOME_LOCATION # What's the cost of this jump? 它是否需要在查找表中搜索每个跳转,或者它是如何工作的?最初(例如8086)跳转的成本与mov的成本没有太大区别 后来CPU添加了缓存,这意味着一些跳转更快(因为它们跳转到的代码在缓存中),而一些跳转较慢(因为它们跳转到的代码不在缓存中) 甚至在后来,CPU添加了“无序”执行,其中条件分支(例如,je SOME_LOCATION)将不得

我一直对组装过程中的跳跃成本感到好奇

cmp ecx, edx
je SOME_LOCATION # What's the cost of this jump?
它是否需要在查找表中搜索每个跳转,或者它是如何工作的?

最初(例如8086)跳转的成本与
mov的成本没有太大区别

后来CPU添加了缓存,这意味着一些跳转更快(因为它们跳转到的代码在缓存中),而一些跳转较慢(因为它们跳转到的代码不在缓存中)

甚至在后来,CPU添加了“无序”执行,其中条件分支(例如,
je SOME_LOCATION
)将不得不等待,直到“先前的指令碰巧并行执行”中的标志变为已知

这意味着

mov esi, edi 
cmp ecx, edx 
je SOME_LOCATION
可能比重新排列要慢

cmp ecx, edx 
mov esi, edi 
je SOME_LOCATION
以增加了解旗帜的机会

甚至在后来,CPU添加了推测性执行。在这种情况下,对于条件分支,CPU只是在它实际知道之前(例如,在知道标志之前)猜测它将分支到哪里,如果它猜错了,它将假装它没有执行错误的指令。更具体地说,推测执行的指令在管道开始时被标记,并在管道结束时(失效时)保持,直到CPU知道它们是否可以提交到可见状态或是否必须丢弃

在那之后,事情变得更加复杂,有了更奇特的分支预测方法,额外的“分支目标”缓冲区,等等

改变代码段的远跳代价更高。在实模式下,这并不坏,因为当
CS
发生变化时,CPU通常只执行“CS.base=value*16”。对于保护模式,它是一个表查找(查找GDT或LDT条目),解码条目,根据条目的类型决定要做什么,然后是一堆保护检查。对于长模式,它有点相似。所有这些都增加了更多的不确定性(例如,表项是否在缓存中?)

除此之外,还有TLB失误等问题。例如,
jmp[indirectAddress]
可能导致
indirectAddress
处的TLB未命中,然后是堆栈顶部的TLB未命中,然后是新指令指针处的TLB未命中;其中,每次TLB未命中可能需要几百个周期

大部分;跳转的成本可以是0个周期(对于正确预测的跳转)到1000个周期之间的任何值;取决于它是哪个CPU,什么类型的跳转,缓存中有什么,分支预测预测预测什么,缓存/TLB未命中,RAM有多快/慢,以及我可能忘记的任何事情。

最初(例如8086),跳转的成本与
mov的成本没有太大区别

后来CPU添加了缓存,这意味着一些跳转更快(因为它们跳转到的代码在缓存中),而一些跳转较慢(因为它们跳转到的代码不在缓存中)

甚至在后来,CPU添加了“无序”执行,其中条件分支(例如,
je SOME_LOCATION
)将不得不等待,直到“先前的指令碰巧并行执行”中的标志变为已知

这意味着

mov esi, edi 
cmp ecx, edx 
je SOME_LOCATION
可能比重新排列要慢

cmp ecx, edx 
mov esi, edi 
je SOME_LOCATION
以增加了解旗帜的机会

甚至在后来,CPU添加了推测性执行。在这种情况下,对于条件分支,CPU只是在它实际知道之前(例如,在知道标志之前)猜测它将分支到哪里,如果它猜错了,它将假装它没有执行错误的指令。更具体地说,推测执行的指令在管道开始时被标记,并在管道结束时(失效时)保持,直到CPU知道它们是否可以提交到可见状态或是否必须丢弃

在那之后,事情变得更加复杂,有了更奇特的分支预测方法,额外的“分支目标”缓冲区,等等

改变代码段的远跳代价更高。在实模式下,这并不坏,因为当
CS
发生变化时,CPU通常只执行“CS.base=value*16”。对于保护模式,它是一个表查找(查找GDT或LDT条目),解码条目,根据条目的类型决定要做什么,然后是一堆保护检查。对于长模式,它有点相似。所有这些都增加了更多的不确定性(例如,表项是否在缓存中?)

除此之外,还有TLB失误等问题。例如,
jmp[indirectAddress]
可能导致
indirectAddress
处的TLB未命中,然后是堆栈顶部的TLB未命中,然后是新指令指针处的TLB未命中;其中,每次TLB未命中可能需要几百个周期


大部分;跳转的成本可以是0个周期(对于正确预测的跳转)到1000个周期之间的任何值;取决于它是哪个CPU,什么类型的跳转,缓存中有什么,分支预测预测预测什么,缓存/TLB未命中,RAM有多快/慢,以及我可能忘记的任何内容。

不,跳转不进行搜索。汇编程序将标签解析为一个地址,在大多数情况下,该地址会转换为当前指令的偏移量。地址或偏移量在指令中进行编码。在运行时,处理器将地址加载到IP寄存器或将偏移量添加到IP寄存器的当前值(以及@Brendan讨论的所有其他影响)

有一种类型的跳转指令可用于从表中获取目标。跳转指令从内存位置读取地址。(该指令指定了一个位置,因此仍然没有“搜索”。)该指令可能如下所示:

jmp table[eax*4]

其中eax是表中包含要跳转到的地址的项的索引。

否,跳转不进行搜索。汇编程序将标签解析为一个地址,在大多数情况下,该地址会转换为当前指令的偏移量