【问题标题】:IF statement ASM and CPU branchingIF 语句 ASM 和 CPU 分支
【发布时间】:2014-02-26 03:32:02
【问题描述】:

仅使用VS2012中的反汇编窗口:

if(p == 7){
00344408  cmp         dword ptr [p],7  
0034440C  jne         main+57h (0344417h)  
    j = 2;
0034440E  mov         dword ptr [j],2  
}
else{
00344415  jmp         main+5Eh (034441Eh)  
    j = 3;
00344417  mov         dword ptr [j],3  
}

我说的跳转表已经实现是正确的吗?如果是这样,这是否仍然会导致 CPU 分支问题,因为程序集仍然必须执行 cmp 命令?

我正在查看 IF 语句的性能成本,并想知道编译器优化到跳转表是否意味着不再有 CPU 分支问题。

【问题讨论】:

  • 我没有看到该代码中使用了任何跳转表。

标签: c performance assembly x86 cpu


【解决方案1】:

这里没有跳转表:两条跳转指令都在某个绝对地址上:

jne         main+57h (0344417h) 
jmp         main+5Eh (034441Eh)

没有间接性。使用跳转表根本不能解决“CPU 分支问题”。有无跳转表的分支预测代价应该差不多。

【讨论】:

  • 啊,好吧,如果我错了,请纠正我,但分支表唯一保存的是多重比较指令?所以跳转表意味着一次比较,if,else if,else if需要多次比较——都导致CPU分支预测错误?
  • 跳转表没有比较。跳转的地址是使用一些数组访问来计算的。您应该阅读stackoverflow.com/questions/48017/what-is-a-jump-tableen.wikipedia.org/wiki/Branch_table
  • 所以分支错误预测只是因为选择了选项 1,然后是选项 3,然后是选项 2,然后是选项 3 等等......并且没有......预测!
【解决方案2】:

我不会称其为跳表。跳转表是一个目标地址数组,索引是根据您正在切换的用户数据动态计算的。您展示的代码只是一个简单的控制流,有两个替代分支,完全是静态编码的控制流。

作为一个典型的例子,if (X) foo() else bar() 变成(伪代码):

jump_if(!X, Label),  foo(),  jump(End),  Label: bar(),  End:

【讨论】:

    【解决方案3】:

    在纯 C 或 C++ 中表达跳转表的最接近方法是使用函数指针数组。

    switch 结构通常成为跳转表,尽管与函数指针数组不同,它们是函数内的间接分支,而不是对新函数的间接调用。

    【讨论】:

      猜你喜欢
      • 2012-12-20
      • 2016-05-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-10
      • 2016-05-24
      • 2023-03-12
      相关资源
      最近更新 更多