comparison doc/disas_examples/x86.fastcall_ms.disas @ 469:984e6652b975

some x86 disas examples, for completion but also while researching struct by val passing on non-x64
author Tassilo Philipp
date Mon, 07 Feb 2022 13:15:49 +0100
parents
children 79e76734bb5c
comparison
equal deleted inserted replaced
468:79b95db3d68f 469:984e6652b975
1 ; #include <stdlib.h>
2 ;
3 ; void leaf_call(int b, int c, int d, int e, int f, int g, int h)
4 ; {
5 ; }
6 ;
7 ; void 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.0 (/Gr for fastcall)
23
24 _b$ = -8
25 _c$ = -4
26 @leaf_call@28 PROC
27 push ebp
28 mov ebp, esp
29 sub esp, 8
30 mov DWORD PTR _c$[ebp], edx
31 mov DWORD PTR _b$[ebp], ecx
32 mov esp, ebp
33 pop ebp
34 ret 20
35 @leaf_call@28 ENDP
36
37 _a$ = -8
38 _b$ = -4
39 _c$ = 8
40 _d$ = 12
41 _e$ = 16
42 _f$ = 20
43 _g$ = 24
44 _h$ = 28
45 @nonleaf_call@32 PROC
46 push ebp ; |
47 mov ebp, esp ; | prolog
48 sub esp, 8 ; |
49 mov DWORD PTR _b$[ebp], edx ; in arg 1 -> local area on stack
50 mov DWORD PTR _a$[ebp], ecx ; in arg 0 -> local area on stack
51 mov ecx, 220 ; |
52 call @alloca@4 ; | call alloca(220) (ecx = arg)
53 mov BYTE PTR [eax], 76 ; 'L' -> alloca()'d space (pointed to by alloca's retval in eax)
54 mov eax, DWORD PTR _h$[ebp] ; |
55 push eax ; |
56 mov ecx, DWORD PTR _g$[ebp] ; |
57 push ecx ; |
58 mov edx, DWORD PTR _f$[ebp] ; | read in args 3-7 from prev frame's param area, and ...
59 push edx ; | ... "push" onto stack as arg 2-6
60 mov eax, DWORD PTR _e$[ebp] ; |
61 push eax ; |
62 mov ecx, DWORD PTR _d$[ebp] ; |
63 push ecx ; |
64 mov edx, DWORD PTR _c$[ebp] ; arg 1 | read from prev frame's param
65 mov ecx, DWORD PTR _b$[ebp] ; arg 0 | area and put in regs
66 call @leaf_call@28 ; push return address and call
67 mov esp, ebp ; |
68 pop ebp ; | epilog
69 ret 24 ; |
70 @nonleaf_call@32 ENDP
71
72 _main PROC
73 push ebp ; | prolog
74 mov ebp, esp ; |
75 push 7 ; arg 7
76 push 6 ; arg 6
77 push 5 ; arg 5
78 push 4 ; arg 4
79 push 3 ; arg 3
80 push 2 ; arg 2
81 mov edx, 1 ; arg 1 (via reg)
82 xor ecx, ecx ; arg 0 (via reg)
83 call @nonleaf_call@32 ; push return address and call
84 xor eax, eax ; return value
85 pop ebp ; |
86 ret 0 ; | epilog
87 _main ENDP
88
89
90
91 ; ---------- structs by value, struct in first call on reg arg boundary ---------->
92 ;
93 ; struct A { int x; short y; char z; long long t; };
94 ;
95 ; struct A leaf_call(struct A a, short b, long long c, char d, int e, int f, int g, long long h)
96 ; {
97 ; a.x += 1;
98 ; return a;
99 ; }
100 ;
101 ; int main()
102 ; {
103 ; struct A a ={9, 99, 23, 12LL};
104 ; leaf_call(a, 1, 2, 3, 4, 5, 6, 7LL);
105 ; return 0;
106 ; }
107
108
109
110 ; output from godbolt compiler explorer w/ msvc 19.0 (/Gr for fastcall)
111
112 _b$ = -8
113 _d$ = -4
114 $T1 = 8
115 _a$ = 12
116 _c$ = 28
117 _e$ = 36
118 _f$ = 40
119 _g$ = 44
120 _h$ = 48
121 @leaf_call@52 PROC
122 push ebp ; |
123 mov ebp, esp ; | prolog
124 sub esp, 8 ; |
125 mov BYTE PTR _d$[ebp], dl ; in arg 3 -> local area on stack
126 mov WORD PTR _b$[ebp], cx ; in arg 1 -> local area on stack
127 mov eax, DWORD PTR _a$[ebp] ; \
128 add eax, 1 ; | get struct's x (from stack args), add 1 and write back
129 mov DWORD PTR _a$[ebp], eax ; /
130 mov ecx, DWORD PTR $T1[ebp] ; get ptr to retval struct passed as hidden arg (+8 to skip retval and saved ebp)
131 mov edx, DWORD PTR _a$[ebp] ; |
132 mov DWORD PTR [ecx], edx ; |
133 mov eax, DWORD PTR _a$[ebp+4] ; |
134 mov DWORD PTR [ecx+4], eax ; | copy modified (b/c of x+=1) struct arg to space of retval
135 mov edx, DWORD PTR _a$[ebp+8] ; |
136 mov DWORD PTR [ecx+8], edx ; |
137 mov eax, DWORD PTR _a$[ebp+12] ; |
138 mov DWORD PTR [ecx+12], eax ; |
139 mov eax, DWORD PTR $T1[ebp] ; return value (= ptr to struct that was passed-in as hidden arg)
140 mov esp, ebp ; |
141 pop ebp ; | epilog
142 ret 48 ; |
143 @leaf_call@52 ENDP
144
145 $T1 = -32
146 _a$ = -16
147 _main PROC
148 push ebp ; |
149 mov ebp, esp ; | prolog
150 sub esp, 32 ; / 32 = 16b local area for struct + 16b space used for retval struct
151 mov DWORD PTR _a$[ebp], 9 ; \ int x
152 mov eax, 99 ; | |
153 mov WORD PTR _a$[ebp+4], ax ; | struct values (local area) | short y
154 mov BYTE PTR _a$[ebp+6], 23 ; | char z
155 mov DWORD PTR _a$[ebp+8], 12 ; | |
156 mov DWORD PTR _a$[ebp+12], 0 ; / | long long t
157 push 0 ; |
158 push 7 ; | arg 7
159 push 6 ; arg 6
160 push 5 ; arg 5
161 push 4 ; arg 4
162 push 0 ; |
163 push 2 ; / arg 2 (via stack b/c not first arg and > 32 bits)
164 sub esp, 16 ; \
165 mov ecx, esp ; |
166 mov edx, DWORD PTR _a$[ebp] ; |
167 mov DWORD PTR [ecx], edx ; |
168 mov eax, DWORD PTR _a$[ebp+4] ; |
169 mov DWORD PTR [ecx+4], eax ; | arg 0 (struct), "pushed" onto stack (fetched from local area)
170 mov edx, DWORD PTR _a$[ebp+8] ; |
171 mov DWORD PTR [ecx+8], edx ; |
172 mov eax, DWORD PTR _a$[ebp+12] ; |
173 mov DWORD PTR [ecx+12], eax ; /
174 lea ecx, DWORD PTR $T1[ebp] ; \ ptr to space used for struct retval (pushed as hidden first arg)
175 push ecx ; |
176 mov dl, 3 ; arg 3 (via reg)
177 mov ecx, 1 ; arg 1 (via reg)
178 call @leaf_call@52 ; push return address and call
179 xor eax, eax ; return value
180 mov esp, ebp ; |
181 pop ebp ; | epilog
182 ret 0 ; |
183 _main ENDP
184
185
186
187 ; vim: ft=asm
188