Assembly 为什么有条件的移动没有';我不能正常工作

Assembly 为什么有条件的移动没有';我不能正常工作,assembly,Assembly,在我编译了下面的代码之后,该函数似乎没有按预期工作 int cread(int *xp){ return (xp?*xp:0); } 我提取汇编版本中的对应项,如下所示 xp在寄存器中%edx movl $0, %eax testl %edx, %edx cmovne (%edx), %eax 有谁能告诉我为什么指针xp即使在测试失败时仍然被cmovne取消引用?当%edx为0时,ZF不是被testl指令设置为1吗?英特尔指令集手册似乎表明,如果不满足条件,则不会读取CMOV

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

int cread(int *xp){

     return (xp?*xp:0);

}
我提取汇编版本中的对应项,如下所示

xp
在寄存器中
%edx

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

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

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

显然,其他人不同意;见明确警告:

如果源操作数是内存操作数,则无论是否满足条件,都将始终读取该操作数。这意味着无论从内存读取中生成什么异常,都将生成。如果内存读取会导致“GP”或“PG”,那么就这样吧

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


我只在它的注册表形式中使用它,它不能陷阱。

cmovne
为“不等于零时移动”,即“ZF==0时移动”;如果
%edx
为0,则不会发生解引用。只需澄清术语;它是“不相等时移动”(又名
cmovnz
-“不等于零时移动”)。如果这是真的,那么编译器在OP的上下文中发出它不是一个错误吗?@500 InternalServerError:是的,这似乎是一个编译器错误。它们并不总是完美的:-{实际上我还有一个问题,编译器如何决定指令的操作数是有符号的还是无符号的,然后相应地设置条件代码寄存器编译时,程序集版本可以是mov$-1%eax、mov$1%edx、mov%eax%edp、add%edx%edp、cmp%eax%edx、cmovg%edp%eax(假设x在%eax中,y在%edx中)。cmovg是基于对~(SF^of)的求值执行的&~ZF,CPU执行指令cmp%eax%edx时是否也会设置CF?请注意,二进制形式的负数-1与2StackOverflow策略所说的相同,您不应该在这个线程中问这个问题。启动另一个StackOverflow问题。这也会使您更容易展示您的示例,作为一个Common,这个示例非常不可读T