Not all conditional expressions can be compiled using conditional moves. Most significantly, the abstract code we have shown evaluates both then-expr and else-expr regardless of the test outcome. If one of those two expressions could possibly generate an error condition or a side effect, this could lead to invalid behavior. As an illustration, consider the following C function:
1 int cread(int *xp){
2 return (xp ? *xp : 0);
3 }
At first, this seems like a good candidate to compile using a conditional move to read the value designated by pointer xp, as shown in the following assembly code:
1 #Invalid implementation of function cread
2 #xp in register %edx
3 movl $0, %eax
4 testl %edx, %edx
5 cmovne (%edx), %eax
This implementation is invalid, however, since the dereferencing of xp by the cmovne instruction occurs even when the test fails, causing a null pointer dereferencing error.
Instead, this code must be compiled using branching code.
A similar case holds when either of the two branches causes a side effect, as illustrated by the following function:
1 /*Global variable*/
2 int lcount = 0;
3 int absdiff_se(int x. int y){
4 return x < y ? (lcount++, y-x) : x-y;
5 }
This function increments global variable lcount as part of then-expr. Thus, branching code must be used to ensure this side effect only occurs when the test condition holds.
这是原话,我这里有些疑惑,这里说的是conditional move的缺点,特别提到的是This implementation is invalid, however, since the dereferencing of xp by the cmovne instruction occurs even when the test fails, causing a null pointer dereferencing error.这句话,我不是很明白,cmovne 指令不就是根据test的结果来转移的吗?为啥后面又提到说cmovne即使test失败了也会调用?求解啊
------解决思路----------------------
看下 intel 的开发手册的卷2 指令集里关于 CMOVcc 的操作过程的描述:
Operation这意味着首先就操作了 DEST 对象了,如果 DEST 无效,就会导致指令异常;所以,整个指令对上面的情况来说,是不合适的。
temp ← DEST
IF condition TRUE
THEN
DEST ← SRC
ELSE
DEST ← temp
FI;
------解决思路----------------------
源操作数会被内部装载,只不过条件测试失败的话它将被抛弃。
所以如果是不合法地址的话。。。