我是你的伟大着作CSAPP 2e的读者。我对第3.6.6章提出了一个问题。
在本章中,作者使用了一个名为cread的函数来表明在某些情况下我们不应该使用条件移动。
函数cread()
如下:
int cread(int* xp) {
return (xp? *xp : 0);
}
此功能的汇编代码为:
1 movl $0 , %eax Set 0 as return value
2 testl %edx , %edx Test xp
3 cmovne (%edx), %eax if !0, dereference xp to get return value
作者强调,如果xp
为空,则xp
的取消引用无效。但正如我所看到的,第1行是xp
是空指针的条件,第3行,如果xp
为空,(%edx)
将不会被复制到{{1}因此,这段代码避免了解除引用空指针的可能性。
此外,当我在CSAPP 3e中查看此问题时,此函数的汇编代码已更改如下:
%eax
我可以在第二个汇编代码中看到第2行中的问题,如果1 cread:
2 movq (%rdi), %rax
3 tests %rdi , %rdi
4 move $0 , %edx
5 cmove %rdx , %rax
6 ret
是空指针,那么这个取消引用是一个错误。但是,我无法弄清楚第一段汇编代码中是否存在相同的错误(实际上我认为这段代码是正确的)。
我的问题是:我的理解是否正确,或者第一段汇编代码中是否存在错误?
答案 0 :(得分:1)
在第三条指令中:
cmovne (%edx), %eax
首先得到(%edx)的值,然后分析条件,最后根据条件将(%edx)移动到%eax。 因此,即使%edx = 0,它仍将访问(%edx)的值,这将导致分段错误。