因此,假设我有以下代码,它给出了三个我认为是不必要的值副本的示例。

为什么将rdi中的值复制到内存位于rbp-0x18,然后复制回rdx?然后将其复制到rsi(额外复制2张)。

最后,为什么将lea + movrbp-0x10转换为rax,然后复制到rdi?是否有任何原因未生成以下代码?

mov    QWORD PTR [rbp-0x18],rdi
mov    rdx,QWORD PTR [rbp-0x18]
lea    rax,[rbp-0x10]
mov    rsi,rdx
mov    rdi,rax
call   4003e0 <strcpy@plt>


(我的猜测是,这只是编译器中代码生成的产物,但是我确保没有x86-64缺少的某些规则。)

#1 楼

没有构件,编译器肯定是可靠的,我的意思是GCC可以生成更好,更快的代码。您生成的代码的第一个版本未优化。为什么呢是由于指定了-O0标志(0级优化==>没有优化),或者是因为没有指定优化标志,并且默认情况下GCC关闭了优化。

下面您将找到同一代码的两个版本。带有-O0标志的版本1。具有-O2标志的版本2。



版本1:

 55                      push   rbp
 48 89 e5                mov    rbp,rsp
 48 81 ec 10 04 00 00    sub    rsp,0x410
 89 bd fc fb ff ff       mov    DWORD PTR [rbp-0x404],edi
 48 89 b5 f0 fb ff ff    mov    QWORD PTR [rbp-0x410],rsi
 48 8b 85 f0 fb ff ff    mov    rax,QWORD PTR [rbp-0x410]
 48 83 c0 08             add    rax,0x8
 48 8b 10                mov    rdx,QWORD PTR [rax]
 48 8d 85 00 fc ff ff    lea    rax,[rbp-0x400]
 48 89 d6                mov    rsi,rdx
 48 89 c7                mov    rdi,rax
 e8 40 fe ff ff          call   400400 <strcpy@plt>
 48 8d 85 00 fc ff ff    lea    rax,[rbp-0x400]
 48 89 c7                mov    rdi,rax
 e8 41 fe ff ff          call   400410 <puts@plt>
 b8 00 00 00 00          mov    eax,0x0
 c9                      leave
 c3                      ret
 66 2e 0f 1f 84 00 00    nop    WORD PTR cs:[rax+rax*1+0x0]
 00 00 00  



版本2:

 48 81 ec 08 04 00 00    sub    rsp,0x408
 48 8b 76 08             mov    rsi,QWORD PTR [rsi+0x8]
 48 89 e7                mov    rdi,rsp
 e8 ad ff ff ff          call   400400 <strcpy@plt>
 48 89 e7                mov    rdi,rsp
 e8 b5 ff ff ff          call   400410 <puts@plt>
 31 c0                   xor    eax,eax
 48 81 c4 08 04 00 00    add    rsp,0x408
 c3                      ret
 0f 1f 00                nop    DWORD PTR [rax]



如果您对GCC执行的优化感兴趣,则应该阅读此链接,也请阅读此链接。您还可以查看GCC峰会出版物。

评论


好吧,这似乎就是我的假设。我正在发布来自战争游戏挑战的代码,我想在那里没有优化是没有道理的。

–大卫
2014年6月5日17:32