471
|
1 ; #include <stdlib.h>
|
|
2 ;
|
|
3 ; void __stdcall leaf_call(int b, int c, int d, int e, int f, int g, int h)
|
|
4 ; {
|
|
5 ; }
|
|
6 ;
|
|
7 ; void __stdcall nonleaf_call(int a, int b, int c, int d, int e, int f, int g, int h)
|
|
8 ; {
|
|
9 ; /* use some local data */
|
|
10 ; *(char*)alloca(220) = 'L';
|
|
11 ; leaf_call(b, c, d, e, f, g, h);
|
|
12 ; }
|
|
13 ;
|
|
14 ; int main()
|
|
15 ; {
|
|
16 ; nonleaf_call(0, 1, 2, 3, 4, 5, 6, 7);
|
|
17 ; return 0;
|
|
18 ; }
|
|
19
|
|
20
|
|
21
|
|
22 ; output from godbolt compiler explorer w/ msvc 19.14 (w/ /GS- for simplicity)
|
|
23
|
|
24 _leaf_call@28 PROC
|
|
25 push ebp
|
|
26 mov ebp, esp
|
|
27 pop ebp
|
|
28 ret 28
|
|
29 _leaf_call@28 ENDP
|
|
30
|
|
31 _b$ = 12
|
|
32 _c$ = 16
|
|
33 _d$ = 20
|
|
34 _e$ = 24
|
|
35 _f$ = 28
|
|
36 _g$ = 32
|
|
37 _h$ = 36
|
|
38 _nonleaf_call@32 PROC
|
|
39 push ebp
|
|
40 mov ebp, esp
|
|
41 push 220
|
|
42 call _alloca
|
|
43 add esp, 4
|
|
44 mov BYTE PTR [eax], 76
|
|
45 mov eax, DWORD PTR _h$[ebp]
|
|
46 push eax
|
|
47 mov ecx, DWORD PTR _g$[ebp]
|
|
48 push ecx
|
|
49 mov edx, DWORD PTR _f$[ebp]
|
|
50 push edx
|
|
51 mov eax, DWORD PTR _e$[ebp]
|
|
52 push eax
|
|
53 mov ecx, DWORD PTR _d$[ebp]
|
|
54 push ecx
|
|
55 mov edx, DWORD PTR _c$[ebp]
|
|
56 push edx
|
|
57 mov eax, DWORD PTR _b$[ebp]
|
|
58 push eax
|
|
59 call _leaf_call@28
|
|
60 pop ebp
|
|
61 ret 32
|
|
62 _nonleaf_call@32 ENDP
|
|
63
|
|
64 _main PROC
|
|
65 push ebp
|
|
66 mov ebp, esp
|
|
67 push 7
|
|
68 push 6
|
|
69 push 5
|
|
70 push 4
|
|
71 push 3
|
|
72 push 2
|
|
73 push 1
|
|
74 push 0
|
|
75 call _nonleaf_call@32
|
|
76 xor eax, eax
|
|
77 pop ebp
|
|
78 ret 0
|
|
79 _main ENDP
|
|
80
|
|
81
|
|
82
|
|
83 ; ---------- structs by value, struct in first call on reg arg boundary ---------->
|
|
84 ;
|
|
85 ; struct A { int x; short y; char z; long long t; };
|
|
86 ;
|
|
87 ; struct A __stdcall leaf_call(struct A a, short b, long long c, char d, int e, int f, int g, long long h)
|
|
88 ; {
|
|
89 ; a.x += 1;
|
|
90 ; return a;
|
|
91 ; }
|
|
92 ;
|
|
93 ; int main()
|
|
94 ; {
|
|
95 ; struct A a = {9, 99, 23, 12LL};
|
|
96 ; leaf_call(a, 1, 2, 3, 4, 5, 6, 7LL);
|
|
97 ; return 0;
|
|
98 ; }
|
|
99
|
|
100
|
|
101
|
|
102 ; output from godbolt compiler explorer w/ msvc 19.14 (w/ /GS- for simplicity)
|
|
103
|
|
104 $T1 = 8
|
|
105 _a$ = 12
|
|
106 _leaf_call@52 PROC
|
|
107 push ebp ; | prolog
|
|
108 mov ebp, esp ; /
|
|
109 mov eax, DWORD PTR _a$[ebp] ; \
|
|
110 add eax, 1 ; | get struct's x (from stack args), add 1 and write back
|
|
111 mov DWORD PTR _a$[ebp], eax ; /
|
|
112 mov ecx, DWORD PTR $T1[ebp] ; get ptr to retval struct passed as hidden arg (+8 to skip retval and saved ebp)
|
|
113 mov edx, DWORD PTR _a$[ebp] ; |
|
|
114 mov DWORD PTR [ecx], edx ; |
|
|
115 mov eax, DWORD PTR _a$[ebp+4] ; |
|
|
116 mov DWORD PTR [ecx+4], eax ; | copy modified (b/c of x+=1) struct arg to space of retval
|
|
117 mov edx, DWORD PTR _a$[ebp+8] ; |
|
|
118 mov DWORD PTR [ecx+8], edx ; |
|
|
119 mov eax, DWORD PTR _a$[ebp+12] ; |
|
|
120 mov DWORD PTR [ecx+12], eax ; |
|
|
121 mov eax, DWORD PTR $T1[ebp] ; return value (= ptr to struct that was passed-in as hidden arg)
|
|
122 pop ebp ; |
|
|
123 ret 56 ; | epilog (56 = stack cleanup of stdcall)
|
|
124 _leaf_call@52 ENDP
|
|
125
|
|
126 $T1 = -32
|
|
127 _a$ = -16
|
|
128 _main PROC
|
|
129 push ebp ; |
|
|
130 mov ebp, esp ; | prolog
|
|
131 sub esp, 32 ; / 32 = 16b local area for struct + 16b space used for retval struct
|
|
132 mov DWORD PTR _a$[ebp], 9 ; \ int x
|
|
133 mov eax, 99 ; | |
|
|
134 mov WORD PTR _a$[ebp+4], ax ; | struct values (local area) | short y
|
|
135 mov BYTE PTR _a$[ebp+6], 23 ; | char z
|
|
136 mov DWORD PTR _a$[ebp+8], 12 ; | |
|
|
137 mov DWORD PTR _a$[ebp+12], 0 ; / | long long t
|
|
138 push 0 ; \
|
|
139 push 7 ; | arg 7
|
|
140 push 6 ; arg 6
|
|
141 push 5 ; arg 5
|
|
142 push 4 ; arg 4
|
|
143 push 3 ; arg 3
|
|
144 push 0 ; |
|
|
145 push 2 ; arg 2
|
|
146 push 1 ; arg 1
|
|
147 sub esp, 16 ; |
|
|
148 mov ecx, esp ; |
|
|
149 mov edx, DWORD PTR _a$[ebp] ; |
|
|
150 mov DWORD PTR [ecx], edx ; |
|
|
151 mov eax, DWORD PTR _a$[ebp+4] ; |
|
|
152 mov DWORD PTR [ecx+4], eax ; | arg 0 (struct), "pushed" onto stack (fetched from local area)
|
|
153 mov edx, DWORD PTR _a$[ebp+8] ; |
|
|
154 mov DWORD PTR [ecx+8], edx ; |
|
|
155 mov eax, DWORD PTR _a$[ebp+12] ; |
|
|
156 mov DWORD PTR [ecx+12], eax ; /
|
|
157 lea ecx, DWORD PTR $T1[ebp] ; \ ptr to space used for struct retval (pushed as hidden first arg)
|
|
158 push ecx ; |
|
|
159 call _leaf_call@52 ; push return address and call
|
|
160 ; (note: cdecl would clean up stack, here)
|
|
161 xor eax, eax ; return value
|
|
162 mov esp, ebp ; |
|
|
163 pop ebp ; | epilog
|
|
164 ret 0 ; |
|
|
165 _main ENDP
|
|
166
|
|
167
|
|
168
|
|
169 ; vim: ft=asm
|
|
170
|