<分区>
我正在做 CSAPP 的练习 3.61,它需要编写一个非常简单的函数来检查指针是否为 NULL
,然后再尝试取消引用它,这应该基于条件移动指令而不是比跳跃。这是我在网上找到的一个例子:
long cond(long* p) {
return (!p) ? 0 : *p;
}
根据claims,该函数可以编译成如下程序集:
cond:
xor eax, eax
test rdi, rdi
cmovne rax, QWORD PTR [rdi]
ret
我在 WSL 上的 Ubuntu 18.04 上运行 GCC 7.3.0(来自 APT 包 gcc/bionic-updates,now 4:7.3.0-3ubuntu2.1 amd64
)。该计算机在 Intel Coffee Lake(即第 8 代 Core-i)处理器上运行。
我尝试了以下命令:
gcc -S a.c -O3
gcc -S a.c -O3 -march=x86-64
gcc -S a.c -O3 -march=core2
gcc -S a.c -O3 -march=k8
老实说,我没能在生成的 a.s
文件中观察到任何差异,因为它们看起来都像
cond:
xorl %eax, %eax
testq %rdi, %rdi
je .L1
movq (%rdi), %rax
.L1:
ret
有没有可能有这样一个函数,可以编译成条件移动,而不需要跳转?
编辑:正如评论中所述,CMOVxx 系列指令无条件加载操作数,只有实际赋值操作是有条件的,因此没有运气放置 *p
(或(%rdi)
)作为CMOV的源操作数,对吗?
claim 是在this page但我认为这是无效的。