浏览这本书的第 3 章,称为计算机系统架构:程序员的视角 https://rads.stackoverflow.com/amzn/click/com/0136108040,据说像这样的实现
testl %eax, %eax
cmovne (%eax), %edx
是无效的,因为如果预测失败,那么我们将取消引用 NULL。它还指出我们应该使用分支代码。
不过,使用条件跳转不会导致相同的结果吗?例如:
.L1:
jmp *%eax
testl %eax, %eax
jne .L1
是否有可能欺骗 gcc 为 x86-32 输出类似的内容?假设我有一个指向函数的指针数组,其中有些是有效的,有些是无效的,并且我调用每个不为 NULL 的指针。
不。您不应该能够检测到乱序操作数获取jmp
指令,如果它是推测执行的一部分,并且由于测试和跳转而被证明是无效的。
The cmove__
指令是如果内存访问操作数会导致故障,则精确记录以导致故障 http://www.rcollins.org/p6/opcodes/CMOV.html,即使条件不满足。换句话说,这不是推测执行。它是指令语义的一部分。这是move到有条件的目的地,而不是获取。
The jmp
指令没有如此记录。
我不明白你的示例代码的意义,因为内存操作没有条件*%eax
. If %eax
包含零,当然是无条件执行中的获取jmp *%eax
会引起故障。这是正确的行为。如果你测试%eax
并跳过错误的参考。
testl %eax, %eax
je .L1
jmp *%eax
.L1:
不可能有问题。推测执行*%eax
除非推测被证明是有效的,即真正的控制路径,否则不会导致故障。这类似于错误操作码、除以零等的行为:正常的程序语义不受推测执行的影响。
真正无序获取和存储的地方do导致各种有趣问题的原因在于多处理。本文及其上一期的第一部分 http://www.linuxjournal.com/article/8212?page=0,0关于这个话题的讨论很精彩。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)