I have this simple C program in a file named test.c :
void fx2(){
int c = 30;
c++;
}
void fx1(){
int b = 20;
b++;
fx2();
}
int main(){
int a = 10;
a++;
fx1();
}
I've compiled this in an Ubuntu ( 22.04.3 ) x86_64 system by using "gcc test.c -o test". Then I used "objdump -d test" and I got this :
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
I've also compiled test.c in a macOS ( Monteray 12.6.5 ) x86_64 system with "clang test.c -o test". Then I used "otool -tV test" and I got this :
(__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
Here's my questions:
Considering this simple C program, can I be 100% sure that otool and objdump show the exact machine instructions contained in the executable "test" ? For example, are the two function prologue instructions
pushq %rbp
andmovq %rsp,%rbp
really contained in the actual executable "test" or can these dis-assemblers omit/add/modify instructions to make the program easier to read and follow ?It looks like gcc and clang in Ubuntu and macOS respectively do use the frame pointers. Can we say that Ubuntu and macOS systems do use frame pointers or would it be more appropriate to say that only the specific compilers gcc and clang in the context of Ubuntu and macOS respectively use the frame pointer ?