I compiled the following code using clang
and gcc
and called both with -O3
:
#include <stdio.h>
#include <stdlib.h>
static void a(int n) {
if (n == 0) return;
printf("descending; a=%i\n", n);
a(n-1);
}
int main() {
a(5);
return 0;
}
Here is the main function gcc
generated (without NOPs at the end):
08048310 <main>:
8048310: 55 push %ebp
8048311: 89 e5 mov %esp,%ebp
8048313: 83 e4 f0 and $0xfffffff0,%esp
8048316: 83 ec 10 sub $0x10,%esp
8048319: c7 44 24 04 05 00 00 movl $0x5,0x4(%esp)
8048320: 00
8048321: c7 04 24 14 85 04 08 movl $0x8048514,(%esp)
8048328: e8 c7 ff ff ff call 80482f4 <printf@plt>
804832d: c7 44 24 04 04 00 00 movl $0x4,0x4(%esp)
8048334: 00
8048335: c7 04 24 14 85 04 08 movl $0x8048514,(%esp)
804833c: e8 b3 ff ff ff call 80482f4 <printf@plt>
8048341: c7 44 24 04 03 00 00 movl $0x3,0x4(%esp)
8048348: 00
8048349: c7 04 24 14 85 04 08 movl $0x8048514,(%esp)
8048350: e8 9f ff ff ff call 80482f4 <printf@plt>
8048355: c7 44 24 04 02 00 00 movl $0x2,0x4(%esp)
804835c: 00
804835d: c7 04 24 14 85 04 08 movl $0x8048514,(%esp)
8048364: e8 8b ff ff ff call 80482f4 <printf@plt>
8048369: c7 44 24 04 01 00 00 movl $0x1,0x4(%esp)
8048370: 00
8048371: c7 04 24 14 85 04 08 movl $0x8048514,(%esp)
8048378: e8 77 ff ff ff call 80482f4 <printf@plt>
804837d: 31 c0 xor %eax,%eax
804837f: c9 leave
8048380: c3 ret
And here's the one from clang
:
080483d0 <main>:
80483d0: 55 push %ebp
80483d1: 89 e5 mov %esp,%ebp
80483d3: 56 push %esi
80483d4: 83 ec 0c sub $0xc,%esp
80483d7: be 05 00 00 00 mov $0x5,%esi
80483dc: 8d 74 26 00 lea 0x0(%esi,%eiz,1),%esi
80483e0: 89 74 24 04 mov %esi,0x4(%esp)
80483e4: c7 04 24 e0 84 04 08 movl $0x80484e0,(%esp)
80483eb: e8 04 ff ff ff call 80482f4 <printf@plt>
80483f0: 4e dec %esi
80483f1: 75 ed jne 80483e0 <main+0x10>
80483f3: 31 c0 xor %eax,%eax
80483f5: 83 c4 0c add $0xc,%esp
80483f8: 5e pop %esi
80483f9: 5d pop %ebp
80483fa: c3 ret
My question is: Is there a good reason why they both generate code that writes the address of the static string on the stack over and over again? For example, why doesn't the code clang
generates look like this instead?
080483d0 <main>:
80483d0: 55 push %ebp
80483d1: 89 e5 mov %esp,%ebp
80483d3: 56 push %esi
80483d4: 83 ec 0c sub $0xc,%esp
80483d7: be 05 00 00 00 mov $0x5,%esi
80483dc: 8d 74 26 00 lea 0x0(%esi,%eiz,1),%esi
80483e0: c7 04 24 e0 84 04 08 movl $0x80484e0,(%esp)
80483e7: 89 74 24 04 mov %esi,0x4(%esp)
80483eb: e8 04 ff ff ff call 80482f4 <printf@plt>
80483f0: 4e dec %esi
80483f1: xx xx jne 80483e7 <main+0x17>
80483f3: 31 c0 xor %eax,%eax
80483f5: 83 c4 0c add $0xc,%esp
80483f8: 5e pop %esi
80483f9: 5d pop %ebp
80483fa: c3 ret