解引用指针之前,空校验条件移动指令[复制]

问题描述 投票:1回答:1

我正在CSAPP,这需要写一个很简单的功能来检查,如果一个指针是试图取消引用前NULL,应在条件移动指令,而不是跳跃基地锻炼3.61。下面是我在网上找到了一个例子:

long cond(long* p) {
    return (!p) ? 0 : *p;
}

根据权利要求中,功能可被编译为以下组件:

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)。计算机上的英特尔咖啡湖运行(即第八根核心-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的源操作数,是不是?

索赔是this page,但我认为这是无效的。

c gcc assembly conditional
1个回答
0
投票

下面是一个分支少版本:

inline long* select(long* p, long* q) {
    uintptr_t a = (uintptr_t)p;
    uintptr_t b = (uintptr_t)q;
    uintptr_t c = !a;
    uintptr_t r = (a & (c - 1)) | (b & (!c - 1));
    return (long*)r;
}

long cond(long* p) {
    long t = 0;
    return *select(p, &t);
}

大会GCC-8.2:

cond(long*):
        mov     QWORD PTR [rsp-8], 0
        xor     eax, eax
        test    rdi, rdi
        sete    al
        lea     rdx, [rax-1]
        neg     rax
        and     rdi, rdx
        lea     rdx, [rsp-8]
        and     rax, rdx
        or      rdi, rax
        mov     rax, QWORD PTR [rdi]
        ret

大会铛-7:

cond(long*):                              # @cond(long*)
        mov     qword ptr [rsp - 8], 0
        xor     eax, eax
        test    rdi, rdi
        lea     rcx, [rsp - 8]
        cmovne  rcx, rax
        or      rcx, rdi
        mov     rax, qword ptr [rcx]
        ret
© www.soinside.com 2019 - 2024. All rights reserved.