我试图更好地理解程序集,目前正在使用一些编译的 c 代码片段。我有以下片段:
#include <stdio.h>
#include <string.h>
int main() {
char b[] = " a nice nice long string";
char c[100];
strcpy(c, b);
printf("Hello World %s\n", c);
strcpy(c, " AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
}
使用gcc hello_world.c -o hello_world
gdb编译并打开后,main 函数的汇编代码如下所示:
0x00000000000006fa <+0>: push rbp
0x00000000000006fb <+1>: mov rbp,rsp
0x00000000000006fe <+4>: sub rsp,0x90
0x0000000000000705 <+11>: mov rax,QWORD PTR fs:0x28
0x000000000000070e <+20>: mov QWORD PTR [rbp-0x8],rax
0x0000000000000712 <+24>: xor eax,eax
0x0000000000000714 <+26>: movabs rax,0x206563696e206120
0x000000000000071e <+36>: movabs rdx,0x6e6f6c206563696e
0x0000000000000728 <+46>: mov QWORD PTR [rbp-0x90],rax
0x000000000000072f <+53>: mov QWORD PTR [rbp-0x88],rdx
0x0000000000000736 <+60>: movabs rax,0x676e697274732067
0x0000000000000740 <+70>: mov QWORD PTR [rbp-0x80],rax
0x0000000000000744 <+74>: mov BYTE PTR [rbp-0x78],0x0
0x0000000000000748 <+78>: lea rdx,[rbp-0x90]
0x000000000000074f <+85>: lea rax,[rbp-0x70]
0x0000000000000753 <+89>: mov rsi,rdx
0x0000000000000756 <+92>: mov rdi,rax
0x0000000000000759 <+95>: call 0x5b0 <strcpy@plt>
0x000000000000075e <+100>: lea rax,[rbp-0x70]
0x0000000000000762 <+104>: mov rsi,rax
0x0000000000000765 <+107>: lea rdi,[rip+0xe8] # 0x854
0x000000000000076c <+114>: mov eax,0x0
0x0000000000000771 <+119>: call 0x5d0 <printf@plt>
0x0000000000000776 <+124>: lea rax,[rbp-0x70]
0x000000000000077a <+128>: movabs rsi,0x4141414141414120
0x0000000000000784 <+138>: movabs rdi,0x4141414141414141
0x000000000000078e <+148>: mov QWORD PTR [rax],rsi
0x0000000000000791 <+151>: mov QWORD PTR [rax+0x8],rdi
0x0000000000000795 <+155>: movabs rdx,0x4141414141414141
0x000000000000079f <+165>: movabs rcx,0x4141414141414141
0x00000000000007a9 <+175>: mov QWORD PTR [rax+0x10],rdx
0x00000000000007ad <+179>: mov QWORD PTR [rax+0x18],rcx
0x00000000000007b1 <+183>: mov BYTE PTR [rax+0x20],0x0
0x00000000000007b5 <+187>: mov eax,0x0
0x00000000000007ba <+192>: mov rcx,QWORD PTR [rbp-0x8]
0x00000000000007be <+196>: xor rcx,QWORD PTR fs:0x28
0x00000000000007c7 <+205>: je 0x7ce <main+212>
0x00000000000007c9 <+207>: call 0x5c0 <__stack_chk_fail@plt>
0x00000000000007ce <+212>: leave
0x00000000000007cf <+213>: ret
我想我明白哪个部分在做什么。但有些事情我不清楚。
- strcpy 仅被调用一次,并且仅在第二个参数是变量时调用。为什么没有调用第二个 strcopy?
- printf 用一个字符串和第二个参数调用。该字符串是从 rip+0xe8 加载的。为什么提供给第二个 strcopy 的字符串没有以相同的方式加载?它在 moveabs 指令中被“硬编码”。
这是由于一些编译器优化吗?有人可以详细说明吗?