5

在我编译下面的代码后,该函数似乎没有按预期工作。

int cread(int *xp){

     return (xp?*xp:0);

}

我提取了汇编版本中的对应部分,如下所示。

xp在注册%edx

movl $0, %eax
testl  %edx, %edx
cmovne (%edx), %eax

谁能告诉我为什么即使测试失败,指针xp仍然被取消引用?cmovne不是由指令ZF设置为什么时候吗?1testl%edx0

4

1 回答 1

3

英特尔指令集手册似乎表明如果条件不满足,则不会读取 CMOV 操作数。(我怀疑手册中给出的指令的“算法”不太正确。)

显然,其他人不同意;请参阅此处的明确警告:

如果源操作数是内存操作数,那么无论是否满足条件,它总是被读取。这意味着无论从内存读取中生成的任何异常都会生成。如果内存读取会导致#GP 或#PG,那就这样吧。

我怀疑原因是这样的:指令解码器读取指令,计算有效地址,并在指令完全解码并准备好执行之前尽早发出内存读取。因此,对内存的读取会提前安排/执行并导致陷阱。直到执行单元实际到达 CMOV,它才知道不需要读取内存,并且太晚启动它会使指令非常慢,并使指令预取逻辑复杂化。

我只在它的注册表形式中使用它,它不能被捕获。

于 2013-06-26T05:25:09.017 回答