; #include <stdlib.h>
;
; void leaf_call(int b, int c, int d, int e, int f, int g, int h)
; {
; }
;
; void nonleaf_call(int a, int b, int c, int d, int e, int f, int g, int h)
; {
; /* use some local data */
; *(char*)alloca(220) = 'L';
; leaf_call(b, c, d, e, f, g, h);
; }
;
; int main()
; {
; nonleaf_call(0, 1, 2, 3, 4, 5, 6, 7);
; return 0;
; }
; output from arch_linux-2011.08.19-x86 w/ gcc 4.6.1
00000000 <leaf_call>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 5d pop %ebp
4: c3 ret
00000005 <nonleaf_call>:
5: 55 push %ebp ; |
6: 89 e5 mov %esp,%ebp ; | prolog
8: 83 ec 38 sub $0x38,%esp ; /
b: b8 10 00 00 00 mov $0x10,%eax ; \ |
10: 83 e8 01 sub $0x1,%eax ; | | creative way to move 250 to eax
13: 05 eb 00 00 00 add $0xeb,%eax ; | /
18: c7 45 f4 10 00 00 00 movl $0x10,-0xc(%ebp) ; | size comp wtf? \
1f: ba 00 00 00 00 mov $0x0,%edx ; | |
24: f7 75 f4 divl -0xc(%ebp) ; | | obviously fastest way to round to multiple of 16
27: 6b c0 10 imul $0x10,%eax,%eax ; | |
2a: 29 c4 sub %eax,%esp ; alloca(220) with size containing some padding computed above
2c: 8d 44 24 1c lea 0x1c(%esp),%eax ; |
30: 83 c0 0f add $0xf,%eax ; | start of alloca()'d memory -> eax, by ...
33: c1 e8 04 shr $0x4,%eax ; | ... using ebx and 2 pointless store/reads in local space as helper to align to 16b
36: c1 e0 04 shl $0x4,%eax ; |
39: c6 00 4c movb $0x4c,(%eax) ; 'L' -> alloca()'d space
3c: 8b 45 24 mov 0x24(%ebp),%eax ; |
3f: 89 44 24 18 mov %eax,0x18(%esp) ; |
43: 8b 45 20 mov 0x20(%ebp),%eax ; |
46: 89 44 24 14 mov %eax,0x14(%esp) ; |
4a: 8b 45 1c mov 0x1c(%ebp),%eax ; |
4d: 89 44 24 10 mov %eax,0x10(%esp) ; |
51: 8b 45 18 mov 0x18(%ebp),%eax ; | read in args 1-7 from prev frame's param area, and ...
54: 89 44 24 0c mov %eax,0xc(%esp) ; | ... "push" onto stack as arg 0-6
58: 8b 45 14 mov 0x14(%ebp),%eax ; |
5b: 89 44 24 08 mov %eax,0x8(%esp) ; |
5f: 8b 45 10 mov 0x10(%ebp),%eax ; |
62: 89 44 24 04 mov %eax,0x4(%esp) ; |
66: 8b 45 0c mov 0xc(%ebp),%eax ; |
69: 89 04 24 mov %eax,(%esp) ; |
6c: e8 fc ff ff ff call 6d <nonleaf_call+0x68> ; push return address and call leaf_call (objdump not from final link but .o)
71: c9 leave ; |
72: c3 ret ; | epilog
00000073 <main>:
73: 55 push %ebp ; |
74: 89 e5 mov %esp,%ebp ; |
76: 83 e4 f0 and $0xfffffff0,%esp ; | prolog
79: 83 ec 20 sub $0x20,%esp ; |
7c: c7 44 24 1c 07 00 00 00 movl $0x7,0x1c(%esp) ; arg 7 -> stack
84: c7 44 24 18 06 00 00 00 movl $0x6,0x18(%esp) ; arg 6 -> stack
8c: c7 44 24 14 05 00 00 00 movl $0x5,0x14(%esp) ; arg 5 -> stack
94: c7 44 24 10 04 00 00 00 movl $0x4,0x10(%esp) ; arg 4 -> stack
9c: c7 44 24 0c 03 00 00 00 movl $0x3,0xc(%esp) ; arg 3 -> stack
a4: c7 44 24 08 02 00 00 00 movl $0x2,0x8(%esp) ; arg 2 -> stack
ac: c7 44 24 04 01 00 00 00 movl $0x1,0x4(%esp) ; arg 1 -> stack
b4: c7 04 24 00 00 00 00 movl $0x0,(%esp) ; arg 0 -> stack
bb: e8 fc ff ff ff call bc <main+0x49> ; push return address and call nonleaf_call (objdump not from final link but .o)
c0: b8 00 00 00 00 mov $0x0,%eax ; return value
c5: c9 leave ; |
c6: c3 ret ; | epilog
; output from darwin-8.0.1-x86 w/ gcc 3.3
_leaf_call:
0: 55 pushl %ebp
1: 89 e5 movl %esp, %ebp
3: 83 ec 08 subl $8, %esp
6: c9 leave
7: c3 retl
_nonleaf_call:
8: 55 pushl %ebp ; |
9: 89 e5 movl %esp, %ebp ; | prolog
b: 83 ec 28 subl $40, %esp ; |
e: 81 ec e0 00 00 00 subl $224, %esp ; alloca(220) - with 4b padding
14: 8d 44 24 20 leal 32(%esp), %eax ; |
18: c6 00 4c movb $76, (%eax) ; / 'L' -> alloca()'d space
1b: 8b 45 24 movl 36(%ebp), %eax ; \
1e: 89 44 24 18 movl %eax, 24(%esp) ; |
22: 8b 45 20 movl 32(%ebp), %eax ; |
25: 89 44 24 14 movl %eax, 20(%esp) ; |
29: 8b 45 1c movl 28(%ebp), %eax ; |
2c: 89 44 24 10 movl %eax, 16(%esp) ; |
30: 8b 45 18 movl 24(%ebp), %eax ; | read in args 1-7 from prev frame's param area, and ...
33: 89 44 24 0c movl %eax, 12(%esp) ; | ... "push" onto stack as arg 0-6
37: 8b 45 14 movl 20(%ebp), %eax ; |
3a: 89 44 24 08 movl %eax, 8(%esp) ; |
3e: 8b 45 10 movl 16(%ebp), %eax ; |
41: 89 44 24 04 movl %eax, 4(%esp) ; |
45: 8b 45 0c movl 12(%ebp), %eax ; |
48: 89 04 24 movl %eax, (%esp) ; |
4b: e8 b0 ff ff ff calll -80 <_leaf_call> ; push return address and call
50: c9 leave ; |
51: c3 retl ; | epilog
52: 90 nop ;
53: 90 nop ;
_main:
54: 55 pushl %ebp ; |
55: 89 e5 movl %esp, %ebp ; | prolog
57: 83 ec 28 subl $40, %esp ; |
5a: c7 44 24 1c 07 00 00 00 movl $7, 28(%esp) ; arg 7 -> stack
62: c7 44 24 18 06 00 00 00 movl $6, 24(%esp) ; arg 6 -> stack
6a: c7 44 24 14 05 00 00 00 movl $5, 20(%esp) ; arg 5 -> stack
72: c7 44 24 10 04 00 00 00 movl $4, 16(%esp) ; arg 4 -> stack
7a: c7 44 24 0c 03 00 00 00 movl $3, 12(%esp) ; arg 3 -> stack
82: c7 44 24 08 02 00 00 00 movl $2, 8(%esp) ; arg 2 -> stack
8a: c7 44 24 04 01 00 00 00 movl $1, 4(%esp) ; arg 1 -> stack
92: c7 04 24 00 00 00 00 movl $0, (%esp) ; arg 0 -> stack
99: e8 6a ff ff ff calll -150 <_nonleaf_call> ; push return address and call
9e: b8 00 00 00 00 movl $0, %eax ; return value
a3: c9 leave ; |
a4: c3 retl ; | epilog
; output from freebsd-9.3-x86 w/ gcc 4.2.1
00000000 <leaf_call>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 5d pop %ebp
4: c3 ret
5: 8d 74 26 00 lea 0x0(%esi),%esi
9: 8d bc 27 00 00 00 00 lea 0x0(%edi),%edi
00000010 <nonleaf_call>:
10: 55 push %ebp ; |
11: 89 e5 mov %esp,%ebp ; | prolog
13: 83 ec 28 sub $0x28,%esp ; |
16: 81 ec f0 00 00 00 sub $0xf0,%esp ; alloca(220) - with padding for 16b alignment
1c: 8d 44 24 1c lea 0x1c(%esp),%eax ; |
20: 89 45 fc mov %eax,-0x4(%ebp) ; |
23: 8b 45 fc mov -0x4(%ebp),%eax ; |
26: 83 c0 0f add $0xf,%eax ; | start of alloca()'d memory -> eax, by ...
29: c1 e8 04 shr $0x4,%eax ; | ... using ebx and 2 pointless store/reads in local space as helper to align to 16b
2c: c1 e0 04 shl $0x4,%eax ; |
2f: 89 45 fc mov %eax,-0x4(%ebp) ; |
32: 8b 45 fc mov -0x4(%ebp),%eax ; |
35: c6 00 4c movb $0x4c,(%eax) ; 'L' -> alloca()'d space
38: 8b 45 24 mov 0x24(%ebp),%eax ; |
3b: 89 44 24 18 mov %eax,0x18(%esp) ; |
3f: 8b 45 20 mov 0x20(%ebp),%eax ; |
42: 89 44 24 14 mov %eax,0x14(%esp) ; |
46: 8b 45 1c mov 0x1c(%ebp),%eax ; |
49: 89 44 24 10 mov %eax,0x10(%esp) ; |
4d: 8b 45 18 mov 0x18(%ebp),%eax ; | read in args 1-7 from prev frame's param area, and ...
50: 89 44 24 0c mov %eax,0xc(%esp) ; | ... "push" onto stack as arg 0-6
54: 8b 45 14 mov 0x14(%ebp),%eax ; |
57: 89 44 24 08 mov %eax,0x8(%esp) ; |
5b: 8b 45 10 mov 0x10(%ebp),%eax ; |
5e: 89 44 24 04 mov %eax,0x4(%esp) ; |
62: 8b 45 0c mov 0xc(%ebp),%eax ; |
65: 89 04 24 mov %eax,(%esp) ; |
68: e8 fc ff ff ff call 69 <nonleaf_call+0x59> ; push return address and call leaf_call (objdump not from final link but .o)
6d: c9 leave ; |
6e: c3 ret ; | epilog
6f: 90 nop ;
00000070 <main>:
70: 8d 4c 24 04 lea 0x4(%esp),%ecx ; |
74: 83 e4 f0 and $0xfffffff0,%esp ; |
77: ff 71 fc pushl -0x4(%ecx) ; |
7a: 55 push %ebp ; | prolog
7b: 89 e5 mov %esp,%ebp ; |
7d: 51 push %ecx ; |
7e: 83 ec 24 sub $0x24,%esp ; |
81: c7 44 24 1c 07 00 00 00 movl $0x7,0x1c(%esp) ; arg 7 -> stack
89: c7 44 24 18 06 00 00 00 movl $0x6,0x18(%esp) ; arg 6 -> stack
91: c7 44 24 14 05 00 00 00 movl $0x5,0x14(%esp) ; arg 5 -> stack
99: c7 44 24 10 04 00 00 00 movl $0x4,0x10(%esp) ; arg 4 -> stack
a1: c7 44 24 0c 03 00 00 00 movl $0x3,0xc(%esp) ; arg 3 -> stack
a9: c7 44 24 08 02 00 00 00 movl $0x2,0x8(%esp) ; arg 2 -> stack
b1: c7 44 24 04 01 00 00 00 movl $0x1,0x4(%esp) ; arg 1 -> stack
b9: c7 04 24 00 00 00 00 movl $0x0,(%esp) ; arg 0 -> stack
c0: e8 fc ff ff ff call c1 <main+0x51> ; push return address and call leaf_call (objdump not from final link but .o)
c5: b8 00 00 00 00 mov $0x0,%eax ; return value
ca: 83 c4 24 add $0x24,%esp ; |
cd: 59 pop %ecx ; |
ce: 5d pop %ebp ; | epilog
cf: 8d 61 fc lea -0x4(%ecx),%esp ; |
d2: c3 ret ; |
; output from gentoo_linux-20191029-x86 w/ gcc 8.3.0
00000000 <leaf_call>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: e8 fc ff ff ff call 4 <leaf_call+0x4>
8: 05 01 00 00 00 add $0x1,%eax
d: 90 nop
e: 5d pop %ebp
f: c3 ret
00000010 <nonleaf_call>:
10: 55 push %ebp
11: 89 e5 mov %esp,%ebp
13: 83 ec 18 sub $0x18,%esp
16: e8 fc ff ff ff call 17 <nonleaf_call+0x7>
1b: 05 01 00 00 00 add $0x1,%eax
20: 65 a1 14 00 00 00 mov %gs:0x14,%eax
26: 89 45 f4 mov %eax,-0xc(%ebp)
29: 31 c0 xor %eax,%eax
2b: b8 10 00 00 00 mov $0x10,%eax
30: 48 dec %eax
31: 05 e8 00 00 00 add $0xe8,%eax
36: b9 10 00 00 00 mov $0x10,%ecx
3b: ba 00 00 00 00 mov $0x0,%edx
40: f7 f1 div %ecx
42: 6b c0 10 imul $0x10,%eax,%eax
45: 29 c4 sub %eax,%esp
47: 89 e0 mov %esp,%eax
49: 83 c0 0f add $0xf,%eax
4c: c1 e8 04 shr $0x4,%eax
4f: c1 e0 04 shl $0x4,%eax
52: c6 00 4c movb $0x4c,(%eax)
55: 83 ec 04 sub $0x4,%esp
58: ff 75 24 pushl 0x24(%ebp)
5b: ff 75 20 pushl 0x20(%ebp)
5e: ff 75 1c pushl 0x1c(%ebp)
61: ff 75 18 pushl 0x18(%ebp)
64: ff 75 14 pushl 0x14(%ebp)
67: ff 75 10 pushl 0x10(%ebp)
6a: ff 75 0c pushl 0xc(%ebp)
6d: e8 fc ff ff ff call 6e <nonleaf_call+0x5e>
72: 83 c4 20 add $0x20,%esp
75: 90 nop
76: 8b 45 f4 mov -0xc(%ebp),%eax
79: 65 33 05 14 00 00 00 xor %gs:0x14,%eax
80: 74 05 je 87 <nonleaf_call+0x77>
82: e8 fc ff ff ff call 83 <nonleaf_call+0x73>
87: c9 leave
88: c3 ret
00000089 <main>:
89: 8d 4c 24 04 lea 0x4(%esp),%ecx ; |
8d: 83 e4 f0 and $0xfffffff0,%esp ; |
90: ff 71 fc pushl -0x4(%ecx) ; |
93: 55 push %ebp ; |
94: 89 e5 mov %esp,%ebp ; | prolog (with some stack protection check call, I think)
96: 51 push %ecx ; |
97: 83 ec 04 sub $0x4,%esp ; |
9a: e8 fc ff ff ff call 9b <main+0x12> ; | unsure@@@ call of stackguard stuff, maybe?. (objdump not from final link but .o)
9f: 05 01 00 00 00 add $0x1,%eax ; | ??? add 1 to ret val from unknown call
a4: 6a 07 push $0x7 ; arg 7 -> stack
a6: 6a 06 push $0x6 ; arg 6 -> stack
a8: 6a 05 push $0x5 ; arg 5 -> stack
aa: 6a 04 push $0x4 ; arg 4 -> stack
ac: 6a 03 push $0x3 ; arg 3 -> stack
ae: 6a 02 push $0x2 ; arg 2 -> stack
b0: 6a 01 push $0x1 ; arg 1 -> stack
b2: 6a 00 push $0x0 ; arg 0 -> stack
b4: e8 fc ff ff ff call b5 <main+0x2c> ; push return address and call nonleaf_call (objdump not from final link but .o)
b9: 83 c4 20 add $0x20,%esp ; ???
bc: b8 00 00 00 00 mov $0x0,%eax ; return value
c1: 8b 4d fc mov -0x4(%ebp),%ecx ; | ???
c4: c9 leave ; |
c5: 8d 61 fc lea -0x4(%ecx),%esp ; | epilog ???
c8: c3 ret ; |
; output from haiku w/ gcc 4.4.4
00000000 <leaf_call>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 5d pop %ebp
4: c3 ret
00000005 <nonleaf_call>:
5: 55 push %ebp
6: 89 e5 mov %esp,%ebp
8: 53 push %ebx
9: 83 ec 04 sub $0x4,%esp
c: e8 00 00 00 00 call 11 <nonleaf_call+0xc>
11: 5b pop %ebx
12: 81 c3 03 00 00 00 add $0x3,%ebx
18: 81 ec f0 00 00 00 sub $0xf0,%esp
1e: 89 e0 mov %esp,%eax
20: 83 c0 0f add $0xf,%eax
23: c1 e8 04 shr $0x4,%eax
26: c1 e0 04 shl $0x4,%eax
29: c6 00 4c movb $0x4c,(%eax)
2c: 83 ec 04 sub $0x4,%esp
2f: ff 75 24 pushl 0x24(%ebp)
32: ff 75 20 pushl 0x20(%ebp)
35: ff 75 1c pushl 0x1c(%ebp)
38: ff 75 18 pushl 0x18(%ebp)
3b: ff 75 14 pushl 0x14(%ebp)
3e: ff 75 10 pushl 0x10(%ebp)
41: ff 75 0c pushl 0xc(%ebp)
44: e8 fc ff ff ff call 45 <nonleaf_call+0x40>
49: 83 c4 20 add $0x20,%esp
4c: 8b 5d fc mov -0x4(%ebp),%ebx
4f: c9 leave
50: c3 ret
00000051 <main>:
51: 8d 4c 24 04 lea 0x4(%esp),%ecx
55: 83 e4 f0 and $0xfffffff0,%esp
58: ff 71 fc pushl -0x4(%ecx)
5b: 55 push %ebp
5c: 89 e5 mov %esp,%ebp
5e: 53 push %ebx
5f: 51 push %ecx
60: e8 00 00 00 00 call 65 <main+0x14>
65: 5b pop %ebx
66: 81 c3 03 00 00 00 add $0x3,%ebx
6c: 6a 07 push $0x7
6e: 6a 06 push $0x6
70: 6a 05 push $0x5
72: 6a 04 push $0x4
74: 6a 03 push $0x3
76: 6a 02 push $0x2
78: 6a 01 push $0x1
7a: 6a 00 push $0x0
7c: e8 fc ff ff ff call 7d <main+0x2c>
81: 83 c4 20 add $0x20,%esp
84: b8 00 00 00 00 mov $0x0,%eax
89: 8d 65 f8 lea -0x8(%ebp),%esp
8c: 83 c4 00 add $0x0,%esp
8f: 59 pop %ecx
90: 5b pop %ebx
91: 5d pop %ebp
92: 8d 61 fc lea -0x4(%ecx),%esp
95: c3 ret
; output from nexenta-1.0.1-b85-x86 w/ gcc 4.0.3
00000000 <leaf_call>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: c9 leave
4: c3 ret
00000005 <nonleaf_call>:
5: 55 push %ebp
6: 89 e5 mov %esp,%ebp
8: 83 ec 08 sub $0x8,%esp
b: 81 ec f0 00 00 00 sub $0xf0,%esp
11: 89 65 fc mov %esp,0xfffffffc(%ebp)
14: 8b 45 fc mov 0xfffffffc(%ebp),%eax
17: 83 c0 0f add $0xf,%eax
1a: c1 e8 04 shr $0x4,%eax
1d: c1 e0 04 shl $0x4,%eax
20: 89 45 fc mov %eax,0xfffffffc(%ebp)
23: 8b 45 fc mov 0xfffffffc(%ebp),%eax
26: c6 00 4c movb $0x4c,(%eax)
29: ff 75 24 pushl 0x24(%ebp)
2c: ff 75 20 pushl 0x20(%ebp)
2f: ff 75 1c pushl 0x1c(%ebp)
32: ff 75 18 pushl 0x18(%ebp)
35: ff 75 14 pushl 0x14(%ebp)
38: ff 75 10 pushl 0x10(%ebp)
3b: ff 75 0c pushl 0xc(%ebp)
3e: e8 fc ff ff ff call 3f <nonleaf_call+0x3a>
43: 83 c4 1c add $0x1c,%esp
46: c9 leave
47: c3 ret
00000048 <main>:
48: 55 push %ebp
49: 89 e5 mov %esp,%ebp
4b: 83 ec 08 sub $0x8,%esp
4e: 83 e4 f0 and $0xfffffff0,%esp
51: b8 00 00 00 00 mov $0x0,%eax
56: 83 c0 0f add $0xf,%eax
59: 83 c0 0f add $0xf,%eax
5c: c1 e8 04 shr $0x4,%eax
5f: c1 e0 04 shl $0x4,%eax
62: 29 c4 sub %eax,%esp
64: 6a 07 push $0x7
66: 6a 06 push $0x6
68: 6a 05 push $0x5
6a: 6a 04 push $0x4
6c: 6a 03 push $0x3
6e: 6a 02 push $0x2
70: 6a 01 push $0x1
72: 6a 00 push $0x0
74: e8 fc ff ff ff call 75 <main+0x2d>
79: 83 c4 20 add $0x20,%esp
7c: b8 00 00 00 00 mov $0x0,%eax
81: c9 leave
82: c3 ret
; output from openbsd-4.0-x86 w/ gcc 3.3.5 (propolice)
00000000 <leaf_call>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: c9 leave
4: c3 ret
00000005 <nonleaf_call>:
5: 55 push %ebp
6: 89 e5 mov %esp,%ebp
8: 83 ec 18 sub $0x18,%esp
b: a1 00 00 00 00 mov 0x0,%eax
10: 89 45 e8 mov %eax,0xffffffe8(%ebp)
13: 81 ec e0 00 00 00 sub $0xe0,%esp
19: 89 e0 mov %esp,%eax
1b: c6 00 4c movb $0x4c,(%eax)
1e: 83 ec 04 sub $0x4,%esp
21: ff 75 24 pushl 0x24(%ebp)
24: ff 75 20 pushl 0x20(%ebp)
27: ff 75 1c pushl 0x1c(%ebp)
2a: ff 75 18 pushl 0x18(%ebp)
2d: ff 75 14 pushl 0x14(%ebp)
30: ff 75 10 pushl 0x10(%ebp)
33: ff 75 0c pushl 0xc(%ebp)
36: e8 fc ff ff ff call 37 <nonleaf_call+0x32>
3b: 83 c4 20 add $0x20,%esp
3e: 8b 45 e8 mov 0xffffffe8(%ebp),%eax
41: 3b 05 00 00 00 00 cmp 0x0,%eax
47: 74 13 je 5c <nonleaf_call+0x57>
49: 83 ec 08 sub $0x8,%esp
4c: ff 75 e8 pushl 0xffffffe8(%ebp)
4f: 68 00 00 00 00 push $0x0
54: e8 fc ff ff ff call 55 <nonleaf_call+0x50>
59: 83 c4 10 add $0x10,%esp
5c: c9 leave
5d: c3 ret
0000005e <main>:
5e: 55 push %ebp
5f: 89 e5 mov %esp,%ebp
61: 83 ec 18 sub $0x18,%esp
64: 83 e4 f0 and $0xfffffff0,%esp
67: b8 00 00 00 00 mov $0x0,%eax
6c: 29 c4 sub %eax,%esp
6e: a1 00 00 00 00 mov 0x0,%eax
73: 89 45 e8 mov %eax,0xffffffe8(%ebp)
76: 6a 07 push $0x7
78: 6a 06 push $0x6
7a: 6a 05 push $0x5
7c: 6a 04 push $0x4
7e: 6a 03 push $0x3
80: 6a 02 push $0x2
82: 6a 01 push $0x1
84: 6a 00 push $0x0
86: e8 fc ff ff ff call 87 <main+0x29>
8b: 83 c4 20 add $0x20,%esp
8e: b8 00 00 00 00 mov $0x0,%eax
93: 8b 55 e8 mov 0xffffffe8(%ebp),%edx
96: 3b 15 00 00 00 00 cmp 0x0,%edx
9c: 74 13 je b1 <main+0x53>
9e: 83 ec 08 sub $0x8,%esp
a1: ff 75 e8 pushl 0xffffffe8(%ebp)
a4: 68 0d 00 00 00 push $0xd
a9: e8 fc ff ff ff call aa <main+0x4c>
ae: 83 c4 10 add $0x10,%esp
b1: c9 leave
b2: c3 ret
; output from godbolt compiler explorer w/ msvc 19.0
_leaf_call PROC
push ebp
mov ebp, esp
pop ebp
ret 0
_leaf_call ENDP
_b$ = 12
_c$ = 16
_d$ = 20
_e$ = 24
_f$ = 28
_g$ = 32
_h$ = 36
_nonleaf_call PROC
push ebp
mov ebp, esp
push 220
call _alloca
add esp, 4
mov BYTE PTR [eax], 76
mov eax, DWORD PTR _h$[ebp]
push eax
mov ecx, DWORD PTR _g$[ebp]
push ecx
mov edx, DWORD PTR _f$[ebp]
push edx
mov eax, DWORD PTR _e$[ebp]
push eax
mov ecx, DWORD PTR _d$[ebp]
push ecx
mov edx, DWORD PTR _c$[ebp]
push edx
mov eax, DWORD PTR _b$[ebp]
push eax
call _leaf_call
add esp, 28
pop ebp
ret 0
_nonleaf_call ENDP
_main PROC
push ebp
mov ebp, esp
push 7
push 6
push 5
push 4
push 3
push 2
push 1
push 0
call _nonleaf_call
add esp, 32
xor eax, eax
pop ebp
ret 0
_main ENDP
; ---------- structs by value, struct in first call on reg arg boundary ---------->
;
; struct A { int x; short y; char z; long long t; };
;
; struct A leaf_call(struct A a, short b, long long c, char d, int e, int f, int g, long long h)
; {
; a.x += 1;
; return a;
; }
;
; int main()
; {
; struct A a = {9, 99, 23, 12LL};
; leaf_call(a, 1, 2, 3, 4, 5, 6, 7LL);
; return 0;
; }
; output from godbolt compiler explorer w/ msvc 19.0
$T1 = 8
_a$ = 12
_leaf_call PROC
push ebp ; | prolog
mov ebp, esp ; /
mov eax, DWORD PTR _a$[ebp] ; \
add eax, 1 ; | get struct's x (from stack args), add 1 and write back
mov DWORD PTR _a$[ebp], eax ; /
mov ecx, DWORD PTR $T1[ebp] ; get ptr to retval struct passed as hidden arg (+8 to skip retval and saved ebp)
mov edx, DWORD PTR _a$[ebp] ; |
mov DWORD PTR [ecx], edx ; |
mov eax, DWORD PTR _a$[ebp+4] ; |
mov DWORD PTR [ecx+4], eax ; | copy modified (b/c of x+=1) struct arg to space of retval
mov edx, DWORD PTR _a$[ebp+8] ; |
mov DWORD PTR [ecx+8], edx ; |
mov eax, DWORD PTR _a$[ebp+12] ; |
mov DWORD PTR [ecx+12], eax ; |
mov eax, DWORD PTR $T1[ebp] ; return value (= ptr to struct that was passed-in as hidden arg)
pop ebp ; |
ret 0 ; | epilog
_leaf_call ENDP
$T1 = -32
_a$ = -16
_main PROC
push ebp ; |
mov ebp, esp ; | prolog
sub esp, 32 ; / 32 = 16b local area for struct + 16b space used for retval struct
mov DWORD PTR _a$[ebp], 9 ; \ int x
mov eax, 99 ; | |
mov WORD PTR _a$[ebp+4], ax ; | struct values (local area) | short y
mov BYTE PTR _a$[ebp+6], 23 ; | char z
mov DWORD PTR _a$[ebp+8], 12 ; | |
mov DWORD PTR _a$[ebp+12], 0 ; / | long long t
push 0 ; \
push 7 ; | arg 7
push 6 ; arg 6
push 5 ; arg 5
push 4 ; arg 4
push 3 ; arg 3
push 0 ; |
push 2 ; arg 2
push 1 ; arg 1
sub esp, 16 ; |
mov ecx, esp ; |
mov edx, DWORD PTR _a$[ebp] ; |
mov DWORD PTR [ecx], edx ; |
mov eax, DWORD PTR _a$[ebp+4] ; |
mov DWORD PTR [ecx+4], eax ; | arg 0 (struct), "pushed" onto stack (fetched from local area)
mov edx, DWORD PTR _a$[ebp+8] ; |
mov DWORD PTR [ecx+8], edx ; |
mov eax, DWORD PTR _a$[ebp+12] ; |
mov DWORD PTR [ecx+12], eax ; /
lea ecx, DWORD PTR $T1[ebp] ; \ ptr to space used for struct retval (pushed as hidden first arg)
push ecx ; |
call _leaf_call ; push return address and call
add esp, 56 ; |
xor eax, eax ; : return value
mov esp, ebp ; |
pop ebp ; | epilog
ret 0 ; |
_main ENDP
; ---------- C++ trivial and non-trivial aggrs passed to C funcs ---------->
;
; struct Trivial { int a; };
; struct NonTrivial { int a; NonTrivial() : a(0) {} NonTrivial(const NonTrivial& rhs) : a(rhs.a) { } };
;
; extern "C" {
;
; void f1(struct Trivial s) { }
; void f2(struct NonTrivial s) { }
;
; void f()
; {
; struct Trivial t;
; struct NonTrivial n;
; int a=1;
; a += 123;
; f1(t);
; a -= 123;
; f2(n);
; a -= 12;
; }
; }
; output from openbsd-4.0-x86 w/ gcc 3.3.5 (propolice)
1c0005a0 <f1>:
1c0005a0: 55 push %ebp
1c0005a1: 89 e5 mov %esp,%ebp
1c0005a3: c9 leave
1c0005a4: c3 ret
1c0005a5: 90 nop
1c0005a6 <f2>:
1c0005a6: 55 push %ebp
1c0005a7: 89 e5 mov %esp,%ebp
1c0005a9: c9 leave
1c0005aa: c3 ret
1c0005ab: 90 nop
1c0005ac <f>:
1c0005ac: 55 push %ebp ;
1c0005ad: 89 e5 mov %esp,%ebp ;
1c0005af: 83 ec 48 sub $0x48,%esp ;
1c0005b2: 83 ec 0c sub $0xc,%esp ;
1c0005b5: 8d 45 d8 lea 0xffffffd8(%ebp),%eax ;
1c0005b8: 50 push %eax ;
1c0005b9: e8 8e 00 00 00 call 1c00064c <_ZN10NonTrivialC1Ev> ; NonTrivial::NonTrivial() / ctor
1c0005be: 83 c4 10 add $0x10,%esp ;
1c0005c1: c7 45 d4 01 00 00 00 movl $0x1,0xffffffd4(%ebp) ;
1c0005c8: 8d 45 d4 lea 0xffffffd4(%ebp),%eax ;
1c0005cb: 83 00 7b addl $0x7b,(%eax) ;
1c0005ce: 83 ec 0c sub $0xc,%esp ;
1c0005d1: 8b 45 f4 mov 0xfffffff4(%ebp),%eax ;
1c0005d4: 50 push %eax ;
1c0005d5: e8 c6 ff ff ff call 1c0005a0 <f1> ; call f1(struct Trivial)
1c0005da: 83 c4 10 add $0x10,%esp ;
1c0005dd: 8d 45 d4 lea 0xffffffd4(%ebp),%eax ;
1c0005e0: 83 28 7b subl $0x7b,(%eax) ;
1c0005e3: 83 ec 0c sub $0xc,%esp ;
1c0005e6: 83 ec 0c sub $0xc,%esp ;
1c0005e9: 8d 45 d8 lea 0xffffffd8(%ebp),%eax ; | |
1c0005ec: 50 push %eax ; | / ptr to n
1c0005ed: 8d 45 b8 lea 0xffffffb8(%ebp),%eax ; | \
1c0005f0: 50 push %eax ; | copy n | ptr to dest of copy of n
1c0005f1: e8 64 00 00 00 call 1c00065a <_ZN10NonTrivialC1ERKS_> ; | NonTrivial::NonTrivial(const NonTrivial&) / copy ctor
1c0005f6: 83 c4 14 add $0x14,%esp ;
1c0005f9: 8d 45 b8 lea 0xffffffb8(%ebp),%eax ; |
1c0005fc: 50 push %eax ; | f2 arg 0 (ptr to copy of struct NonTrivial), via ptr as non-trivial
1c0005fd: e8 a4 ff ff ff call 1c0005a6 <f2> ; call f2(struct NonTrivial)
1c000602: 83 c4 10 add $0x10,%esp ;
1c000605: 8d 45 d4 lea 0xffffffd4(%ebp),%eax ;
1c000608: 83 28 0c subl $0xc,(%eax) ;
1c00060b: c9 leave ;
1c00060c: c3 ret ;
1c00060d: 90 nop ;
; ... snip, removed code of ctor and copy ctor ...
; ---------- C++ trivial and non-trivial aggrs as return values ---------->
;
; struct Trivial { int a; };
; struct NonTrivial { int a; NonTrivial() : a(0) {} NonTrivial(const NonTrivial& rhs) : a(rhs.a) { } };
;
; extern "C" {
; struct Trivial f1() { return Trivial(); }
; }
;
; struct NonTrivial f2() { return NonTrivial(); }
;
; extern "C" {
; void f()
; {
; int a=1;
; a += 123;
; struct Trivial t = f1();
; a -= 123;
; struct NonTrivial n = f2();
; a -= 12;
; }
; }
; output from openbsd-4.0-x86 w/ gcc 3.3.5 (propolice)
1c000920 <f1>:
1c000920: 55 push %ebp
1c000921: 89 e5 mov %esp,%ebp
1c000923: 83 ec 04 sub $0x4,%esp
1c000926: c7 45 fc 00 00 00 00 movl $0x0,0xfffffffc(%ebp)
1c00092d: 8b 45 fc mov 0xfffffffc(%ebp),%eax
1c000930: c9 leave
1c000931: c3 ret
1c000932 <_Z2f2v>:
1c000932: 55 push %ebp
1c000933: 89 e5 mov %esp,%ebp
1c000935: 53 push %ebx
1c000936: 83 ec 04 sub $0x4,%esp
1c000939: 8b 5d 08 mov 0x8(%ebp),%ebx
1c00093c: 83 ec 0c sub $0xc,%esp
1c00093f: 53 push %ebx
1c000940: e8 87 00 00 00 call 1c0009cc <_ZN10NonTrivialC1Ev>
1c000945: 83 c4 10 add $0x10,%esp
1c000948: 89 d8 mov %ebx,%eax
1c00094a: 8b 5d fc mov 0xfffffffc(%ebp),%ebx
1c00094d: c9 leave
1c00094e: c2 04 00 ret $0x4
1c000951: 90 nop
1c000952 <f>:
1c000952: 55 push %ebp ;
1c000953: 89 e5 mov %esp,%ebp ;
1c000955: 83 ec 28 sub $0x28,%esp ;
1c000958: c7 45 f4 01 00 00 00 movl $0x1,0xfffffff4(%ebp) ; a = 1
1c00095f: 8d 45 f4 lea 0xfffffff4(%ebp),%eax ; |
1c000962: 83 00 7b addl $0x7b,(%eax) ; | a += 12
1c000965: e8 b6 ff ff ff call 1c000920 <f1> ; call f1()
1c00096a: 89 45 f0 mov %eax,0xfffffff0(%ebp) ; retval (trivial struct <= 32bits, returned via eax)
1c00096d: 8d 45 f4 lea 0xfffffff4(%ebp),%eax ; |
1c000970: 83 28 7b subl $0x7b,(%eax) ; | a -= 123
1c000973: 8d 45 d8 lea 0xffffffd8(%ebp),%eax ; space (at top of stack) to hold non-triv retval -> eax
1c000976: 83 ec 0c sub $0xc,%esp ; grow stack by 12
1c000979: 50 push %eax ; hidden first arg: ptr to space for retval
1c00097a: e8 b3 ff ff ff call 1c000932 <_Z2f2v> ; call f2()
1c00097f: 83 c4 0c add $0xc,%esp ; shrink stack back by 12
1c000982: 8d 45 f4 lea 0xfffffff4(%ebp),%eax ; |
1c000985: 83 28 0c subl $0xc,(%eax) ; | a -= 12
1c000988: c9 leave ;
1c000989: c3 ret ;
; ---------- cdecl-declared (explicit) C++ thiscall w/ msvc ---------->
;
; class C {
; public:
; float __cdecl m(int i) const { return float(i + 123); }
; };
;
; extern "C" {
; float f()
; {
; C c;
; return c.m(27);
; }
; }
; output from godbolt compiler explorer w/ msvc 19.0
tv68 = -8
tv67 = -4
_i$ = 12
float C::m(int)const PROC
push ebp ;
mov ebp, esp ;
sub esp, 8 ;
mov eax, DWORD PTR _i$[ebp] ;
add eax, 123 ; |
mov DWORD PTR tv67[ebp], eax ; / in arg + 123, pushed onto stack
fild DWORD PTR tv67[ebp] ; \
fstp DWORD PTR tv68[ebp] ; | float cast and put return value in fp0
fld DWORD PTR tv68[ebp] ; |
mov esp, ebp ;
pop ebp ;
ret 0 ;
float C::m(int)const ENDP
_c$ = -1
_f PROC ;
push ebp ;
mov ebp, esp ;
push ecx ;
push 27 ; arg 1
lea eax, DWORD PTR _c$[ebp] ; |
push eax ; | arg 0 (this ptr)
call float C::m(int)const ; call C::m()
add esp, 8 ;
mov esp, ebp ;
pop ebp ;
ret 0 ;
_f ENDP
; vim: ft=asm