assembly 缺少优化:mov al,[mem] to bitfield-插入一个新的低位字节到整数中

3zwjbxry  于 2023-06-23  发布在  其他
关注(0)|答案(1)|浏览(100)

我想替换整数中的最低字节。在x86上,这就是mov al, [mem],但我似乎无法让编译器输出这个。我是否错过了一个明显的代码模式,我是否误解了什么,或者这只是一个错过的优化?

unsigned insert_1(const unsigned* a, const unsigned char* b)
{
    return (*a & ~255) | *b;
}
unsigned insert_2(const unsigned* a, const unsigned char* b)
{
    return *a >> 8 << 8 | *b;
}

GCC实际上使用了al,但只是为了归零。

mov     eax, DWORD PTR [rdi]
        movzx   edx, BYTE PTR [rsi]
        xor     al, al
        or      eax, edx
        ret

Clang几乎逐字编译了两者

mov     ecx, -256
        and     ecx, dword ptr [rdi]
        movzx   eax, byte ptr [rsi]
        or      eax, ecx
        ret
kknvjkwl

kknvjkwl1#

在x86上,这就是mov al, [mem],但我似乎无法让编译器输出这个。
试试这个,不需要算术:

unsigned insert_4(const unsigned* a, const unsigned char* b)
{
    unsigned int t = *a;
    unsigned char *tcp = (unsigned char *) & t;
    tcp[0] = *b;
    return t;
}
insert_4(unsigned int const*, unsigned char const*):
        mov     eax, DWORD PTR [rdi]
        mov     al, BYTE PTR [rsi]
        ret

有点古怪,我知道,但编译器擅长删除间接和地址为局部变量(采取了几次尝试,虽然..)。
godbolt x86-64 gcc 13.1 -O3
使用union的替代方法:

unsigned insert_5(const unsigned* a, const unsigned char* b)
{
    union {
        unsigned int ui;
        unsigned char uc;
    } u;
    u.ui = *a;
    u.uc = *b;
    return u.ui;
}

godbolt x86-64 gcc 13.1 -O3
请注意,这些解决方案是特定于端序的,尽管它看起来像是您正在寻找的,并且可以根据需要针对其他端序进行调整。

相关问题