assembly - 分支预测会使我的程序崩溃吗?

标签 assembly cpu-architecture x86 branch-prediction

这本书的第 3 章名为 Computer Systems Architecture: A programmer's perspective ,据说这样的实现

testl %eax, %eax
cmovne (%eax), %edx

无效,因为如果预测失败,那么我们将进行 NULL 解引用。它还指出我们应该使用分支代码。

不过,使用条件跳转不会导致相同的结果吗?例如:

.L1:
jmp *%eax

testl %eax, %eax
jne .L1

是否有可能欺骗 gcc 为 x86-32 输出类似的内容?假设我有一个指向函数的指针数组,其中有些是有效的,有些是无效的,并且我调用每个不为 NULL 的指针。

最佳答案

没有。如果 jmp 指令是由于测试和跳转而被证明无效的推测执行的一部分,您应该无法检测到该指令的乱序操作数获取。

cmove__ 指令是 precisely documented to cause a fault if a memory access operand would cause a fault ,即使条件不满足。换句话说,这不是投机执行。它是指令语义的一部分。有条件的是移动到目的地,而不是获取。

jmp 指令没有如此记录。

我不明白你的示例代码的要点,因为内存操作*%eax没有条件。如果%eax包含零,那么无条件执行jmp *%eax时的取指肯定会导致错误。这是正确的行为。如果您测试 %eax 并跳过错误引用。

testl %eax, %eax
je .L1
jmp *%eax
.L1:

不可能有问题。 *%eax 的推测执行不会导致错误,除非推测被证明是有效的,即真正的控制路径。这类似于错误操作码、除以零等的行为:正常的程序语义不受推测执行的影响。

无序读取和存储真正导致各种有趣问题的地方是在多重处理中。 This article and also its first part in the preceeding issue关于这个主题的讨论非常精彩。

关于assembly - 分支预测会使我的程序崩溃吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24611405/

相关文章:

caching - 为什么 MASKMOVDQU 没有扩展到 256 位和 512 位存储?

c++ - 硬件 SIMD vector 指针和相应类型之间的 `reinterpret_cast` 是未定义的行为吗?

assembly - 文字 VS 立即操作数

assembly - rbp 不允许作为 SIB 基础?

target - 使用 FASM 的 Mach-O 二进制文件

linux - 程序集 'Segmentation Fault' 尝试打印十进制数时

c - 等待多个信号量或多个消息队列

CPU 和数据对齐

cpu-architecture - MESI-读取当前正在修改的数据时会发生什么?

linux - 为什么 Linux/gnu 链接器选择地址 0x400000?