为什么这个编译器不允许这样做的例子导致使用cmov引用空指针?

时间:2015-11-27 19:18:48

标签: c assembly x86

C代码:

int cread(int *xp) {
    return (xp ? *xp : 0);
}

汇编代码:(使用条件移动指令从教科书中获取编译器不允许做的示例)

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

这是计算机系统:程序员的角度(第2版)中使用的示例,表明如果条件的任一分支导致无法使用条件数据传输编译代码错误。在这种情况下,错误将是取消引用xp的空指针。

我知道xp被解除引用,但我不明白xp如何成为空指针。不会依赖指针作为参数传递给函数吗?

2 个答案:

答案 0 :(得分:3)

汇编代码在技术上是有效的,但如果输入为NULL并且因此与C代码的行为不匹配则会出错。鉴于事情的重点是在这种情况下返回零而不是错误,这是错误的。 C等价物是:

int cread(int *xp) {
    int val = *xp;
    return (xp ? val : 0);
}

正如您所看到的,它首先取消引用xp,然后才检查xp是否为NULL,因此这显然不适用于NULL输入。< / p>

答案 1 :(得分:2)

如果您拨打电话

cread(0);

cmovene指令会出错,因为它会评估*xp,即使该值永远不会被使用。

在汇编语言中,这由(%dx)表示。即无论%dx的值是什么,都会dx中的地址内容。

cmov的价值一般都受到质疑。例如,Linus Torvalds不是粉丝。