在我编译下面的代码后,该功能似乎没有按预期工作。
int cread(int *xp){
return (xp?*xp:0);
}
我提取了汇编版本中的对应部分,如下所示。
xp
在寄存器中%edx
movl $0, %eax
testl %edx, %edx
cmovne (%edx), %eax
谁能告诉我为什么指针xp
仍然被取消引用cmovne
即使测试失败?不是ZF
set to 1
by testl
指令时%edx
is 0
?
英特尔指令集手册似乎表明,如果不满足条件,则不会读取 CMOV 操作数。 (我怀疑手册中给出的说明的“算法”不太正确。)
显然,其他人不同意;请参阅明确的警告here http://www.rcollins.org/p6/opcodes/CMOV.html:
如果源操作数是内存操作数,则始终读取它,无论是否满足条件。这意味着无论内存读取产生什么异常,都将生成。如果内存读取会导致#GP 或#PG,那就这样吧。
我怀疑原因是这样的:指令解码器读取指令,计算有效地址,并在指令完全解码并准备好执行之前尽早发出内存读取。因此,对内存的读取会提前计划/执行并导致陷阱。直到执行单元实际到达 CMOV 时,它才知道不需要内存读取,那么晚启动它会使指令非常慢,并使指令预取逻辑复杂化。
我只使用它的寄存器-寄存器形式,它不能捕获。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)