【问题标题】:Assembly move instruction seems to be useless [duplicate]装配移动指令似乎没用[重复]
【发布时间】:2020-09-18 20:18:32
【问题描述】:

我正在努力学习汇编。我反汇编了一个简单的 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 () 处移入堆栈,rsi 的值在 rbp-0x20 (+12) 处移入堆栈。然后 rbp-0x18 处的值被移动到 rax(+16),它将再次移动到 rdi(+20)。为什么这样做?为什么不直接使用 rdi 或至少将 rbp-0x18 直接移动到 rdi,而不是通过 rax(在 处)?这可以将指令保存在 +20

【问题讨论】:

  • 编译时尝试启用优化。使用gcc,尝试指定-O3,看看你会得到什么。
  • 我使用godbolt.org来查看代码和优化之间的区别,这可以帮助你
  • 它将传入的参数保留在堆栈中(供以后使用,或者如果未优化,则仅仅因为它是函数的基本构造的一部分),然后使用其中一个进行嵌套调用参数,因为该参数存在于堆栈中(未优化),它需要从堆栈中读取它。推送和调用是函数构建中的两个独立子结构。堆栈帧,然后保存参数,然后进行调用,这里分别表示了三个不同的东西。

标签: c assembly disassembly instructions


【解决方案1】:

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

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

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

【讨论】:

  • 我认为在 while 循环的末尾有一个额外的; 可以使优化变得非常容易,不是吗?
猜你喜欢
  • 1970-01-01
  • 2014-11-03
  • 1970-01-01
  • 1970-01-01
  • 2013-09-11
  • 2018-01-25
  • 1970-01-01
  • 2019-03-11
  • 2016-02-11
相关资源
最近更新 更多