我在名为 test.c 的文件中有这个简单的 C 程序:
void fx2(){
int c = 30;
c++;
}
void fx1(){
int b = 20;
b++;
fx2();
}
int main(){
int a = 10;
a++;
fx1();
}
我使用“gcc test.c -o test”在 Ubuntu (22.04.3) x86_64 系统中编译了这个。 然后我使用“objdump -d test”,得到了这个:
0000000000001129 <fx2>:
1129: f3 0f 1e fa endbr64
112d: 55 push %rbp
112e: 48 89 e5 mov %rsp,%rbp
1131: c7 45 fc 1e 00 00 00 movl $0x1e,-0x4(%rbp)
1138: 83 45 fc 01 addl $0x1,-0x4(%rbp)
113c: 90 nop
113d: 5d pop %rbp
113e: c3 ret
000000000000113f <fx1>:
113f: f3 0f 1e fa endbr64
1143: 55 push %rbp
1144: 48 89 e5 mov %rsp,%rbp
1147: 48 83 ec 10 sub $0x10,%rsp
114b: c7 45 fc 14 00 00 00 movl $0x14,-0x4(%rbp)
1152: 83 45 fc 01 addl $0x1,-0x4(%rbp)
1156: b8 00 00 00 00 mov $0x0,%eax
115b: e8 c9 ff ff ff call 1129 <fx2>
1160: 90 nop
1161: c9 leave
1162: c3 ret
0000000000001163 <main>:
1163: f3 0f 1e fa endbr64
1167: 55 push %rbp
1168: 48 89 e5 mov %rsp,%rbp
116b: 48 83 ec 10 sub $0x10,%rsp
116f: c7 45 fc 0a 00 00 00 movl $0xa,-0x4(%rbp)
1176: 83 45 fc 01 addl $0x1,-0x4(%rbp)
117a: b8 00 00 00 00 mov $0x0,%eax
117f: e8 bb ff ff ff call 113f <fx1>
1184: b8 00 00 00 00 mov $0x0,%eax
1189: c9 leave
118a: c3 ret
我还在 macOS (Monteray 12.6.5) x86_64 系统中使用“clang test.c -o test”编译了 test.c。然后我使用“otool -tV test”,得到了这个:
(__TEXT,__text) section
_fx2:
0000000100003f40 pushq %rbp
0000000100003f41 movq %rsp, %rbp
0000000100003f44 movl $0x1e, -0x4(%rbp)
0000000100003f4b movl -0x4(%rbp), %eax
0000000100003f4e addl $0x1, %eax
0000000100003f51 movl %eax, -0x4(%rbp)
0000000100003f54 popq %rbp
0000000100003f55 retq
0000000100003f56 nopw %cs:(%rax,%rax)
_fx1:
0000000100003f60 pushq %rbp
0000000100003f61 movq %rsp, %rbp
0000000100003f64 subq $0x10, %rsp
0000000100003f68 movl $0x14, -0x4(%rbp)
0000000100003f6f movl -0x4(%rbp), %eax
0000000100003f72 addl $0x1, %eax
0000000100003f75 movl %eax, -0x4(%rbp)
0000000100003f78 callq _fx2
0000000100003f7d addq $0x10, %rsp
0000000100003f81 popq %rbp
0000000100003f82 retq
0000000100003f83 nopw %cs:(%rax,%rax)
0000000100003f8d nopl (%rax)
_main:
0000000100003f90 pushq %rbp
0000000100003f91 movq %rsp, %rbp
0000000100003f94 subq $0x10, %rsp
0000000100003f98 movl $0xa, -0x4(%rbp)
0000000100003f9f movl -0x4(%rbp), %eax
0000000100003fa2 addl $0x1, %eax
0000000100003fa5 movl %eax, -0x4(%rbp)
0000000100003fa8 callq _fx1
0000000100003fad xorl %eax, %eax
0000000100003faf addq $0x10, %rsp
0000000100003fb3 popq %rbp
0000000100003fb4 retq
这是我的问题:
考虑到这个简单的 C 程序,我可以 100% 确定 otool 和 objdump 显示可执行测试中包含的确切机器指令吗?例如,两个函数序言指令 Pushq %rbp 和 movq %rsp,%rbp" 是否真正包含在实际的可执行“测试”中,或者这些反汇编器可以省略/添加/修改指令以使程序更易于阅读和遵循?
看起来 Ubuntu 和 macOS 中的 gcc 和 clang 分别使用了帧指针。我们是否可以说 Ubuntu 和 macOS 系统确实使用了帧指针,或者更合适的说法是只有 Ubuntu 和 macOS 上下文中的特定编译器 gcc 和 clang 分别使用了帧指针?