装配移动指令似乎没用

Assembly move instruction seems to be useless

我正在努力学习汇编。我反汇编了一个简单的C程序并用gdb调试了它。但我注意到的一件事是值的移动非常频繁。

   0x0000555555555231 <+0>:     push   rbp
   0x0000555555555232 <+1>:     mov    rbp,rsp
   0x0000555555555235 <+4>:     sub    rsp,0x20

   0x0000555555555239 <+8>:     mov    QWORD PTR [rbp-0x18],rdi
   0x000055555555523d <+12>:    mov    QWORD PTR [rbp-0x20],rsi
   0x0000555555555241 <+16>:    mov    rax,QWORD PTR [rbp-0x18]
   0x0000555555555245 <+20>:    mov    rdi,rax
   0x0000555555555248 <+23>:    call   0x5555555551d9 <get_file_size>

rdi 的值移到 rbp-0x18(<+8>)处的堆栈,rsi 的值移到 rbp-0x20(+12)处的堆栈。然后 rbp-0x18 的值被移动到 rax(+16),它会再次被移动到 rdi(+20)。为什么这样做?为什么不直接使用 rdi 或者至少将 rbp-0x18 直接移动到 rdi 而不是通过 rax (at <+16>)?这可以将指令保存在 +20

如果你想从中学习一些汇编程序,没有启用任何优化的编译没有多大意义。

这里有一个优化如何更改生成的代码的示例。

https://godbolt.org/z/YBdLRZ

char *foo(char *dest, const char *src, size_t len)
{
    char *savedDest = dest;
    size_t index = 0;
    if(len)
    {
        while(--len && (dest[index] = src[index]));
        index++;
        *dest = 0;
    }
    return savedDest;
}

无优化

foo:
        push    rbp
        mov     rbp, rsp
        mov     QWORD PTR [rbp-24], rdi
        mov     QWORD PTR [rbp-32], rsi
        mov     QWORD PTR [rbp-40], rdx
        mov     rax, QWORD PTR [rbp-24]
        mov     QWORD PTR [rbp-8], rax
        mov     QWORD PTR [rbp-16], 0
        cmp     QWORD PTR [rbp-40], 0
        je      .L2
.L4:
        sub     QWORD PTR [rbp-40], 1
        cmp     QWORD PTR [rbp-40], 0
        je      .L3
        mov     rdx, QWORD PTR [rbp-32]
        mov     rax, QWORD PTR [rbp-16]
        add     rdx, rax
        mov     rcx, QWORD PTR [rbp-24]
        mov     rax, QWORD PTR [rbp-16]
        add     rax, rcx
        movzx   edx, BYTE PTR [rdx]
        mov     BYTE PTR [rax], dl
        movzx   eax, BYTE PTR [rax]
        test    al, al
        jne     .L4
.L3:
        add     QWORD PTR [rbp-16], 1
        mov     rax, QWORD PTR [rbp-24]
        mov     BYTE PTR [rax], 0
.L2:
        mov     rax, QWORD PTR [rbp-8]
        pop     rbp
        ret

并优化尺寸

foo:
        mov     rax, rdi
        test    rdx, rdx
        je      .L2
.L4:
        dec     rdx
        je      .L3
        mov     cl, BYTE PTR [rsi]
        mov     BYTE PTR [rax], cl
        test    cl, cl
        jne     .L4
.L3:
        mov     BYTE PTR [rax], 0
.L2:
        ret