Rev 8978 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 8978 | Rev 8979 | ||
---|---|---|---|
1 | ; Macroinstructions for defining and calling procedures |
1 | ; Macroinstructions for defining and calling procedures |
2 | 2 | ||
3 | ; @brief Directly call STDCALL procedure |
3 | ; @brief Directly call STDCALL procedure |
4 | ; @param proc Callee name |
4 | ; @param proc Callee name |
5 | ; @param arg Arguments to pass |
5 | ; @param arg Arguments to pass |
6 | macro stdcall proc,[arg] |
6 | macro stdcall proc,[arg] |
7 | { common |
7 | { common |
8 | if ~ arg eq |
8 | if ~ arg eq |
9 | reverse |
9 | reverse |
10 | pushd arg |
10 | pushd arg |
11 | common |
11 | common |
12 | end if |
12 | end if |
13 | call proc } |
13 | call proc } |
14 | 14 | ||
15 | ; @brief Indirectly call STDCALL procedure |
15 | ; @brief Indirectly call STDCALL procedure |
16 | ; @param proc Callee name |
16 | ; @param proc Callee name |
17 | ; @param arg Arguments to pass |
17 | ; @param arg Arguments to pass |
18 | macro invoke proc,[arg] |
18 | macro invoke proc,[arg] |
19 | { common |
19 | { common |
20 | if ~ arg eq |
20 | if ~ arg eq |
21 | reverse |
21 | reverse |
22 | pushd arg |
22 | pushd arg |
23 | common |
23 | common |
24 | end if |
24 | end if |
25 | call [proc] } |
25 | call [proc] } |
26 | 26 | ||
27 | ; @brief Directly call CDECL procedure |
27 | ; @brief Directly call CDECL procedure |
28 | ; @param proc Callee name |
28 | ; @param proc Callee name |
29 | ; @param arg Arguments to pass |
29 | ; @param arg Arguments to pass |
30 | macro ccall proc,[arg] |
30 | macro ccall proc,[arg] |
31 | { common |
31 | { common |
32 | size@ccall = 0 |
32 | size@ccall = 0 |
33 | if ~ arg eq |
33 | if ~ arg eq |
34 | reverse |
34 | reverse |
35 | pushd arg |
35 | pushd arg |
36 | size@ccall = size@ccall+4 |
36 | size@ccall = size@ccall+4 |
37 | common |
37 | common |
38 | end if |
38 | end if |
39 | call proc |
39 | call proc |
40 | if size@ccall |
40 | if size@ccall |
41 | add esp, size@ccall |
41 | add esp, size@ccall |
42 | end if } |
42 | end if } |
43 | 43 | ||
44 | ; @brief Indirectly call CDECL procedure |
44 | ; @brief Indirectly call CDECL procedure |
45 | ; @param proc Callee name |
45 | ; @param proc Callee name |
46 | ; @param arg Arguments to pass |
46 | ; @param arg Arguments to pass |
47 | macro cinvoke proc,[arg] |
47 | macro cinvoke proc,[arg] |
48 | { common |
48 | { common |
49 | size@ccall = 0 |
49 | size@ccall = 0 |
50 | if ~ arg eq |
50 | if ~ arg eq |
51 | reverse |
51 | reverse |
52 | pushd arg |
52 | pushd arg |
53 | size@ccall = size@ccall+4 |
53 | size@ccall = size@ccall+4 |
54 | common |
54 | common |
55 | end if |
55 | end if |
56 | call [proc] |
56 | call [proc] |
57 | if size@ccall |
57 | if size@ccall |
58 | add esp, size@ccall |
58 | add esp, size@ccall |
59 | end if } |
59 | end if } |
60 | 60 | ||
61 | ; @brief Define a procedure.\n |
61 | ; @brief Define a procedure.\n |
62 | ; Calling convention for the procedure may be defined before parameter |
62 | ; Calling convention for the procedure may be defined before parameter |
63 | ; list using `stdcall` or `c` word like this:\n |
63 | ; list using `stdcall` or `c` word like this:\n |
64 | ; `proc name stdcall, param0, param1`\n |
64 | ; `proc name stdcall, param0, param1`\n |
65 | ; List of registers used in the procedure may be specified before |
65 | ; List of registers used in the procedure may be specified before |
66 | ; parameter list using `uses` word like this:\n |
66 | ; parameter list using `uses` word like this:\n |
67 | ; `proc name uses eax ebx ecx, param0, param1`\n |
67 | ; `proc name uses eax ebx ecx, param0, param1`\n |
68 | ; If you need to specify both calling convention and used registers |
68 | ; If you need to specify both calling convention and used registers |
69 | ; put calling convention first and then `uses` statement like this:\n |
69 | ; put calling convention first and then `uses` statement like this:\n |
70 | ; `proc name stdcall uses ebx ecx edx, param0, param1` |
70 | ; `proc name stdcall uses ebx ecx edx, param0, param1`\n |
71 | ; @param args Name of the procedure and a comma-separated argument list. |
71 | ; The defined procedure should be ended using `endp` macro. |
- | 72 | ; @param args Name of the procedure and a comma-separated argument list. |
|
72 | ; Type of any parameter may be specified by semicolon after its |
73 | ; Type of any parameter may be specified by semicolon after its |
73 | ; name like this:\n |
74 | ; name like this:\n |
74 | ; `proc name param0:dword, param1:qword`. |
75 | ; `proc name param0:dword, param1:qword`. |
75 | macro proc [args] |
76 | macro proc [args] |
76 | { common |
77 | { common |
77 | match name params, args> |
78 | match name params, args> |
78 | \{ define@proc name, |
79 | \{ define@proc name, |
79 | 80 | ||
80 | prologue@proc equ prologuedef |
81 | prologue@proc equ prologuedef |
81 | 82 | ||
82 | ; @dont_give_a_doxygen |
83 | ; @dont_give_a_doxygen |
83 | macro prologuedef procname,flag,parmbytes,localbytes,reglist |
84 | macro prologuedef procname,flag,parmbytes,localbytes,reglist |
84 | { local loc |
85 | { local loc |
85 | loc = (localbytes+3) and (not 3) |
86 | loc = (localbytes+3) and (not 3) |
86 | parmbase@proc equ ebp+8 |
87 | parmbase@proc equ ebp+8 |
87 | localbase@proc equ ebp-loc |
88 | localbase@proc equ ebp-loc |
88 | if parmbytes | localbytes |
89 | if parmbytes | localbytes |
89 | push ebp |
90 | push ebp |
90 | mov ebp, esp |
91 | mov ebp, esp |
91 | if localbytes |
92 | if localbytes |
92 | sub esp, loc |
93 | sub esp, loc |
93 | end if |
94 | end if |
94 | end if |
95 | end if |
95 | irps reg, reglist \{ push reg \} } |
96 | irps reg, reglist \{ push reg \} } |
96 | 97 | ||
97 | epilogue@proc equ epiloguedef |
98 | epilogue@proc equ epiloguedef |
98 | 99 | ||
99 | ; @dont_give_a_doxygen |
100 | ; @dont_give_a_doxygen |
100 | macro epiloguedef procname,flag,parmbytes,localbytes,reglist |
101 | macro epiloguedef procname,flag,parmbytes,localbytes,reglist |
101 | { irps reg, reglist \{ reverse pop reg \} |
102 | { irps reg, reglist \{ reverse pop reg \} |
102 | if parmbytes | localbytes |
103 | if parmbytes | localbytes |
103 | leave |
104 | leave |
104 | end if |
105 | end if |
105 | if flag and 10000b |
106 | if flag and 10000b |
106 | retn |
107 | retn |
107 | else |
108 | else |
108 | retn parmbytes |
109 | retn parmbytes |
109 | end if } |
110 | end if } |
110 | 111 | ||
111 | close@proc equ |
112 | close@proc equ |
112 | 113 | ||
113 | ; @dont_give_a_doxygen |
114 | ; @dont_give_a_doxygen |
114 | macro define@proc name,statement |
115 | macro define@proc name,statement |
115 | { local params,flag,regs,parmbytes,localbytes,current |
116 | { local params,flag,regs,parmbytes,localbytes,current |
116 | if used name |
117 | if used name |
117 | name: |
118 | name: |
118 | match =stdcall args, statement \{ params equ args |
119 | match =stdcall args, statement \{ params equ args |
119 | flag = 11b \} |
120 | flag = 11b \} |
120 | match =stdcall, statement \{ params equ |
121 | match =stdcall, statement \{ params equ |
121 | flag = 11b \} |
122 | flag = 11b \} |
122 | match =c args, statement \{ params equ args |
123 | match =c args, statement \{ params equ args |
123 | flag = 10001b \} |
124 | flag = 10001b \} |
124 | match =c, statement \{ params equ |
125 | match =c, statement \{ params equ |
125 | flag = 10001b \} |
126 | flag = 10001b \} |
126 | match =params, params \{ params equ statement |
127 | match =params, params \{ params equ statement |
127 | flag = 0 \} |
128 | flag = 0 \} |
128 | match =uses reglist=,args, params \{ regs equ reglist |
129 | match =uses reglist=,args, params \{ regs equ reglist |
129 | params equ args \} |
130 | params equ args \} |
130 | match =regs =uses reglist, regs params \{ regs equ reglist |
131 | match =regs =uses reglist, regs params \{ regs equ reglist |
131 | params equ \} |
132 | params equ \} |
132 | match =regs, regs \{ regs equ \} |
133 | match =regs, regs \{ regs equ \} |
133 | match prologue:reglist, prologue@proc: |
134 | match prologue:reglist, prologue@proc: |
134 | virtual at parmbase@proc |
135 | virtual at parmbase@proc |
135 | match =,args, params \{ defargs@proc args \} |
136 | match =,args, params \{ defargs@proc args \} |
136 | match =args@proc args, args@proc params \{ defargs@proc args \} |
137 | match =args@proc args, args@proc params \{ defargs@proc args \} |
137 | parmbytes = $-(parmbase@proc) |
138 | parmbytes = $-(parmbase@proc) |
138 | end virtual |
139 | end virtual |
139 | name # % = parmbytes/4 |
140 | name # % = parmbytes/4 |
140 | all@vars equ |
141 | all@vars equ |
141 | current = 0 |
142 | current = 0 |
142 | macro locals |
143 | macro locals |
143 | \{ virtual at localbase@proc+current |
144 | \{ virtual at localbase@proc+current |
144 | macro label def \\{ match . type,def> \\\{ deflocal@proc .,label, |
145 | macro label def \\{ match . type,def> \\\{ deflocal@proc .,label, |
145 | struc db [val] \\{ \common deflocal@proc .,db,val \\} |
146 | struc db [val] \\{ \common deflocal@proc .,db,val \\} |
146 | struc du [val] \\{ \common deflocal@proc .,du,val \\} |
147 | struc du [val] \\{ \common deflocal@proc .,du,val \\} |
147 | struc dw [val] \\{ \common deflocal@proc .,dw,val \\} |
148 | struc dw [val] \\{ \common deflocal@proc .,dw,val \\} |
148 | struc dp [val] \\{ \common deflocal@proc .,dp,val \\} |
149 | struc dp [val] \\{ \common deflocal@proc .,dp,val \\} |
149 | struc dd [val] \\{ \common deflocal@proc .,dd,val \\} |
150 | struc dd [val] \\{ \common deflocal@proc .,dd,val \\} |
150 | struc dt [val] \\{ \common deflocal@proc .,dt,val \\} |
151 | struc dt [val] \\{ \common deflocal@proc .,dt,val \\} |
151 | struc dq [val] \\{ \common deflocal@proc .,dq,val \\} |
152 | struc dq [val] \\{ \common deflocal@proc .,dq,val \\} |
152 | struc rb cnt \\{ deflocal@proc .,rb cnt, \\} |
153 | struc rb cnt \\{ deflocal@proc .,rb cnt, \\} |
153 | struc rw cnt \\{ deflocal@proc .,rw cnt, \\} |
154 | struc rw cnt \\{ deflocal@proc .,rw cnt, \\} |
154 | struc rp cnt \\{ deflocal@proc .,rp cnt, \\} |
155 | struc rp cnt \\{ deflocal@proc .,rp cnt, \\} |
155 | struc rd cnt \\{ deflocal@proc .,rd cnt, \\} |
156 | struc rd cnt \\{ deflocal@proc .,rd cnt, \\} |
156 | struc rt cnt \\{ deflocal@proc .,rt cnt, \\} |
157 | struc rt cnt \\{ deflocal@proc .,rt cnt, \\} |
157 | struc rq cnt \\{ deflocal@proc .,rq cnt, \\} \} |
158 | struc rq cnt \\{ deflocal@proc .,rq cnt, \\} \} |
158 | macro endl |
159 | macro endl |
159 | \{ purge label |
160 | \{ purge label |
160 | restruc db,du,dw,dp,dd,dt,dq |
161 | restruc db,du,dw,dp,dd,dt,dq |
161 | restruc rb,rw,rp,rd,rt,rq |
162 | restruc rb,rw,rp,rd,rt,rq |
162 | current = $-(localbase@proc) |
163 | current = $-(localbase@proc) |
163 | end virtual \} |
164 | end virtual \} |
164 | macro ret operand |
165 | macro ret operand |
165 | \{ match any, operand \\{ retn operand \\} |
166 | \{ match any, operand \\{ retn operand \\} |
166 | match , operand \\{ match epilogue:reglist, epilogue@proc: |
167 | match , operand \\{ match epilogue:reglist, epilogue@proc: |
167 | macro finish@proc |
168 | macro finish@proc |
168 | \{ localbytes = current |
169 | \{ localbytes = current |
169 | match close:reglist, close@proc: |
170 | match close:reglist, close@proc: |
170 | end if \} } |
171 | end if \} } |
171 | 172 | ||
172 | ; @dont_give_a_doxygen |
173 | ; @dont_give_a_doxygen |
173 | macro defargs@proc [arg] |
174 | macro defargs@proc [arg] |
174 | { common |
175 | { common |
175 | if ~ arg eq |
176 | if ~ arg eq |
176 | forward |
177 | forward |
177 | local ..arg,current@arg |
178 | local ..arg,current@arg |
178 | match argname:type, arg |
179 | match argname:type, arg |
179 | \{ current@arg equ argname |
180 | \{ current@arg equ argname |
180 | label ..arg type |
181 | label ..arg type |
181 | argname equ ..arg |
182 | argname equ ..arg |
182 | if dqword eq type |
183 | if dqword eq type |
183 | dd ?,?,?,? |
184 | dd ?,?,?,? |
184 | else if tbyte eq type |
185 | else if tbyte eq type |
185 | dd ?,?,? |
186 | dd ?,?,? |
186 | else if qword eq type | pword eq type |
187 | else if qword eq type | pword eq type |
187 | dd ?,? |
188 | dd ?,? |
188 | else |
189 | else |
189 | dd ? |
190 | dd ? |
190 | end if \} |
191 | end if \} |
191 | match =current@arg,current@arg |
192 | match =current@arg,current@arg |
192 | \{ current@arg equ arg |
193 | \{ current@arg equ arg |
193 | arg equ ..arg |
194 | arg equ ..arg |
194 | ..arg dd ? \} |
195 | ..arg dd ? \} |
195 | common |
196 | common |
196 | args@proc equ current@arg |
197 | args@proc equ current@arg |
197 | forward |
198 | forward |
198 | restore current@arg |
199 | restore current@arg |
199 | common |
200 | common |
200 | end if } |
201 | end if } |
201 | 202 | ||
202 | ; @dont_give_a_doxygen |
203 | ; @dont_give_a_doxygen |
203 | macro deflocal@proc name,def,[val] { name def val } |
204 | macro deflocal@proc name,def,[val] { name def val } |
204 | 205 | ||
205 | ; @dont_give_a_doxygen |
206 | ; @dont_give_a_doxygen |
206 | macro deflocal@proc name,def,[val] |
207 | macro deflocal@proc name,def,[val] |
207 | { common |
208 | { common |
208 | match vars, all@vars \{ all@vars equ all@vars, \} |
209 | match vars, all@vars \{ all@vars equ all@vars, \} |
209 | all@vars equ all@vars name |
210 | all@vars equ all@vars name |
210 | forward |
211 | forward |
211 | local ..var,..tmp |
212 | local ..var,..tmp |
212 | ..var def val |
213 | ..var def val |
213 | match =?, val \{ ..tmp equ \} |
214 | match =?, val \{ ..tmp equ \} |
214 | match any =?, val \{ ..tmp equ \} |
215 | match any =?, val \{ ..tmp equ \} |
215 | match any (=?), val \{ ..tmp equ \} |
216 | match any (=?), val \{ ..tmp equ \} |
216 | match =label, def \{ ..tmp equ \} |
217 | match =label, def \{ ..tmp equ \} |
217 | match tmp : value, ..tmp : val |
218 | match tmp : value, ..tmp : val |
218 | \{ tmp: end virtual |
219 | \{ tmp: end virtual |
219 | initlocal@proc ..var,def value |
220 | initlocal@proc ..var,def value |
220 | virtual at tmp\} |
221 | virtual at tmp\} |
221 | common |
222 | common |
222 | match first rest, ..var, \{ name equ first \} } |
223 | match first rest, ..var, \{ name equ first \} } |
223 | 224 | ||
224 | struc label type { label . type } |
225 | struc label type { label . type } |
225 | 226 | ||
226 | ; @dont_give_a_doxygen |
227 | ; @dont_give_a_doxygen |
227 | macro initlocal@proc name,def |
228 | macro initlocal@proc name,def |
228 | { virtual at name |
229 | { virtual at name |
229 | def |
230 | def |
230 | size@initlocal = $ - name |
231 | size@initlocal = $ - name |
231 | end virtual |
232 | end virtual |
232 | position@initlocal = 0 |
233 | position@initlocal = 0 |
233 | while size@initlocal > position@initlocal |
234 | while size@initlocal > position@initlocal |
234 | virtual at name |
235 | virtual at name |
235 | def |
236 | def |
236 | if size@initlocal - position@initlocal < 2 |
237 | if size@initlocal - position@initlocal < 2 |
237 | current@initlocal = 1 |
238 | current@initlocal = 1 |
238 | load byte@initlocal byte from name+position@initlocal |
239 | load byte@initlocal byte from name+position@initlocal |
239 | else if size@initlocal - position@initlocal < 4 |
240 | else if size@initlocal - position@initlocal < 4 |
240 | current@initlocal = 2 |
241 | current@initlocal = 2 |
241 | load word@initlocal word from name+position@initlocal |
242 | load word@initlocal word from name+position@initlocal |
242 | else |
243 | else |
243 | current@initlocal = 4 |
244 | current@initlocal = 4 |
244 | load dword@initlocal dword from name+position@initlocal |
245 | load dword@initlocal dword from name+position@initlocal |
245 | end if |
246 | end if |
246 | end virtual |
247 | end virtual |
247 | if current@initlocal = 1 |
248 | if current@initlocal = 1 |
248 | mov byte [name+position@initlocal], byte@initlocal |
249 | mov byte [name+position@initlocal], byte@initlocal |
249 | else if current@initlocal = 2 |
250 | else if current@initlocal = 2 |
250 | mov word [name+position@initlocal], word@initlocal |
251 | mov word [name+position@initlocal], word@initlocal |
251 | else |
252 | else |
252 | mov dword [name+position@initlocal], dword@initlocal |
253 | mov dword [name+position@initlocal], dword@initlocal |
253 | end if |
254 | end if |
254 | position@initlocal = position@initlocal + current@initlocal |
255 | position@initlocal = position@initlocal + current@initlocal |
255 | end while } |
256 | end while } |
256 | 257 | ||
- | 258 | ; @brief Mark the end of a procedure created by `proc` macro |
|
257 | macro endp |
259 | macro endp |
258 | { purge ret,locals,endl |
260 | { purge ret,locals,endl |
259 | finish@proc |
261 | finish@proc |
260 | purge finish@proc |
262 | purge finish@proc |
261 | restore regs@proc |
263 | restore regs@proc |
262 | match all,args@proc \{ restore all \} |
264 | match all,args@proc \{ restore all \} |
263 | restore args@proc |
265 | restore args@proc |
264 | match all,all@vars \{ restore all \} } |
266 | match all,all@vars \{ restore all \} } |
265 | 267 | ||
266 | macro local [var] |
268 | macro local [var] |
267 | { common |
269 | { common |
268 | locals |
270 | locals |
269 | forward done@local equ |
271 | forward done@local equ |
270 | match varname[count]:vartype, var |
272 | match varname[count]:vartype, var |
271 | \{ match =BYTE, vartype \\{ varname rb count |
273 | \{ match =BYTE, vartype \\{ varname rb count |
272 | restore done@local \\} |
274 | restore done@local \\} |
273 | match =WORD, vartype \\{ varname rw count |
275 | match =WORD, vartype \\{ varname rw count |
274 | restore done@local \\} |
276 | restore done@local \\} |
275 | match =DWORD, vartype \\{ varname rd count |
277 | match =DWORD, vartype \\{ varname rd count |
276 | restore done@local \\} |
278 | restore done@local \\} |
277 | match =PWORD, vartype \\{ varname rp count |
279 | match =PWORD, vartype \\{ varname rp count |
278 | restore done@local \\} |
280 | restore done@local \\} |
279 | match =QWORD, vartype \\{ varname rq count |
281 | match =QWORD, vartype \\{ varname rq count |
280 | restore done@local \\} |
282 | restore done@local \\} |
281 | match =TBYTE, vartype \\{ varname rt count |
283 | match =TBYTE, vartype \\{ varname rt count |
282 | restore done@local \\} |
284 | restore done@local \\} |
283 | match =DQWORD, vartype \\{ label varname dqword |
285 | match =DQWORD, vartype \\{ label varname dqword |
284 | rq count+count |
286 | rq count+count |
285 | restore done@local \\} |
287 | restore done@local \\} |
286 | match , done@local \\{ virtual |
288 | match , done@local \\{ virtual |
287 | varname vartype |
289 | varname vartype |
288 | end virtual |
290 | end virtual |
289 | rb count*sizeof.\#vartype |
291 | rb count*sizeof.\#vartype |
290 | restore done@local \\} \} |
292 | restore done@local \\} \} |
291 | match :varname:vartype, done@local:var |
293 | match :varname:vartype, done@local:var |
292 | \{ match =BYTE, vartype \\{ varname db ? |
294 | \{ match =BYTE, vartype \\{ varname db ? |
293 | restore done@local \\} |
295 | restore done@local \\} |
294 | match =WORD, vartype \\{ varname dw ? |
296 | match =WORD, vartype \\{ varname dw ? |
295 | restore done@local \\} |
297 | restore done@local \\} |
296 | match =DWORD, vartype \\{ varname dd ? |
298 | match =DWORD, vartype \\{ varname dd ? |
297 | restore done@local \\} |
299 | restore done@local \\} |
298 | match =PWORD, vartype \\{ varname dp ? |
300 | match =PWORD, vartype \\{ varname dp ? |
299 | restore done@local \\} |
301 | restore done@local \\} |
300 | match =QWORD, vartype \\{ varname dq ? |
302 | match =QWORD, vartype \\{ varname dq ? |
301 | restore done@local \\} |
303 | restore done@local \\} |
302 | match =TBYTE, vartype \\{ varname dt ? |
304 | match =TBYTE, vartype \\{ varname dt ? |
303 | restore done@local \\} |
305 | restore done@local \\} |
304 | match =DQWORD, vartype \\{ label varname dqword |
306 | match =DQWORD, vartype \\{ label varname dqword |
305 | dq ?,? |
307 | dq ?,? |
306 | restore done@local \\} |
308 | restore done@local \\} |
307 | match , done@local \\{ varname vartype |
309 | match , done@local \\{ varname vartype |
308 | restore done@local \\} \} |
310 | restore done@local \\} \} |
309 | match ,done@local |
311 | match ,done@local |
310 | \{ var |
312 | \{ var |
311 | restore done@local \} |
313 | restore done@local \} |
312 | common |
314 | common |
313 | endl }>> |
315 | endl }>> |