]>
Commit | Line | Data |
---|---|---|
c7de829c WD |
1 | ;**************************************************************************** |
2 | ;* | |
3 | ;* ======================================================================== | |
4 | ;* | |
5 | ;* The contents of this file are subject to the SciTech MGL Public | |
6 | ;* License Version 1.0 (the "License"); you may not use this file | |
7 | ;* except in compliance with the License. You may obtain a copy of | |
8 | ;* the License at http://www.scitechsoft.com/mgl-license.txt | |
9 | ;* | |
10 | ;* Software distributed under the License is distributed on an | |
11 | ;* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or | |
12 | ;* implied. See the License for the specific language governing | |
13 | ;* rights and limitations under the License. | |
14 | ;* | |
15 | ;* The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc. | |
16 | ;* | |
17 | ;* The Initial Developer of the Original Code is SciTech Software, Inc. | |
18 | ;* All Rights Reserved. | |
19 | ;* | |
20 | ;* ======================================================================== | |
21 | ;* | |
22 | ;* Language: NetWide Assembler (NASM) or Turbo Assembler (TASM) | |
23 | ;* Environment: Any Intel Environment | |
24 | ;* | |
25 | ;* Description: Macros to provide memory model independant assembly language | |
26 | ;* module for C programming. Supports the large and flat memory | |
27 | ;* models. | |
28 | ;* | |
29 | ;* The defines that you should use when assembling modules that | |
30 | ;* use this macro package are: | |
31 | ;* | |
32 | ;* __LARGE__ Assemble for 16-bit large model | |
33 | ;* __FLAT__ Assemble for 32-bit FLAT memory model | |
34 | ;* __NOU__ No underscore for all external C labels | |
35 | ;* __NOU_VAR__ No underscore for global variables only | |
36 | ;* | |
37 | ;* The default settings are for 16-bit large memory model with | |
38 | ;* leading underscores for symbol names. | |
39 | ;* | |
40 | ;* The main intent of the macro file is to enable programmers | |
41 | ;* to write _one_ set of source that can be assembled to run | |
42 | ;* in either 16 bit real and protected modes or 32 bit | |
43 | ;* protected mode without the need to riddle the code with | |
44 | ;* 'if flatmodel' style conditional assembly (it is still there | |
45 | ;* but nicely hidden by a macro layer that enhances the | |
46 | ;* readability and understandability of the resulting code). | |
47 | ;* | |
48 | ;**************************************************************************** | |
49 | ||
50 | ; Include the appropriate version in here depending on the assembler. NASM | |
51 | ; appears to always try and parse code, even if it is in a non-compiling | |
52 | ; block of a ifdef expression, and hence crashes if we include the TASM | |
53 | ; macro package in the same header file. Hence we split the macros up into | |
54 | ; two separate header files. | |
55 | ||
56 | ifdef __NASM_MAJOR__ | |
57 | ||
58 | ;============================================================================ | |
59 | ; Macro package when compiling with NASM. | |
60 | ;============================================================================ | |
61 | ||
62 | ; Turn off underscores for globals if disabled for all externals | |
63 | ||
64 | %ifdef __NOU__ | |
65 | %define __NOU_VAR__ | |
66 | %endif | |
67 | ||
68 | ; Define the __WINDOWS__ symbol if we are compiling for any Windows | |
69 | ; environment | |
70 | ||
71 | %ifdef __WINDOWS16__ | |
72 | %define __WINDOWS__ 1 | |
73 | %endif | |
74 | %ifdef __WINDOWS32__ | |
75 | %define __WINDOWS__ 1 | |
76 | %define __WINDOWS32_386__ 1 | |
77 | %endif | |
78 | ||
79 | ; Macros for accessing 'generic' registers | |
80 | ||
81 | %ifdef __FLAT__ | |
82 | %idefine _ax eax | |
83 | %idefine _bx ebx | |
84 | %idefine _cx ecx | |
85 | %idefine _dx edx | |
86 | %idefine _si esi | |
87 | %idefine _di edi | |
88 | %idefine _bp ebp | |
89 | %idefine _sp esp | |
90 | %idefine _es | |
91 | %idefine UCHAR BYTE ; Size of a character | |
92 | %idefine USHORT WORD ; Size of a short | |
93 | %idefine UINT DWORD ; Size of an integer | |
94 | %idefine ULONG DWORD ; Size of a long | |
95 | %idefine BOOL DWORD ; Size of a boolean | |
96 | %idefine DPTR DWORD ; Size of a data pointer | |
97 | %idefine FDPTR FWORD ; Size of a far data pointer | |
98 | %idefine NDPTR DWORD ; Size of a near data pointer | |
99 | %idefine CPTR DWORD ; Size of a code pointer | |
100 | %idefine FCPTR FWORD ; Size of a far code pointer | |
101 | %idefine NCPTR DWORD ; Size of a near code pointer | |
102 | %idefine FPTR NEAR ; Distance for function pointers | |
103 | %idefine DUINT dd ; Declare a integer variable | |
104 | %idefine intsize 4 | |
105 | %idefine flatmodel 1 | |
106 | %else | |
107 | %idefine _ax ax | |
108 | %idefine _bx bx | |
109 | %idefine _cx cx | |
110 | %idefine _dx dx | |
111 | %idefine _si si | |
112 | %idefine _di di | |
113 | %idefine _bp bp | |
114 | %idefine _sp sp | |
115 | %idefine _es es: | |
116 | %idefine UCHAR BYTE ; Size of a character | |
117 | %idefine USHORT WORD ; Size of a short | |
118 | %idefine UINT WORD ; Size of an integer | |
119 | %idefine ULONG DWORD ; Size of a long | |
120 | %idefine BOOL WORD ; Size of a boolean | |
121 | %idefine DPTR DWORD ; Size of a data pointer | |
122 | %idefine FDPTR DWORD ; Size of a far data pointer | |
123 | %idefine NDPTR WORD ; Size of a near data pointer | |
124 | %idefine CPTR DWORD ; Size of a code pointer | |
125 | %idefine FCPTR DWORD ; Size of a far code pointer | |
126 | %idefine NCPTR WORD ; Size of a near code pointer | |
127 | %idefine FPTR FAR ; Distance for function pointers | |
128 | %idefine DUINT dw ; Declare a integer variable | |
129 | %idefine intsize 2 | |
130 | %endif | |
131 | %idefine invert ~ | |
132 | %idefine offset | |
133 | %idefine use_nasm | |
134 | ||
135 | ; Convert all jumps to near jumps, since NASM does not so this automatically | |
136 | ||
137 | %idefine jo jo near | |
138 | %idefine jno jno near | |
139 | %idefine jz jz near | |
140 | %idefine jnz jnz near | |
141 | %idefine je je near | |
142 | %idefine jne jne near | |
143 | %idefine jb jb near | |
144 | %idefine jbe jbe near | |
145 | %idefine ja ja near | |
146 | %idefine jae jae near | |
147 | %idefine jl jl near | |
148 | %idefine jle jle near | |
149 | %idefine jg jg near | |
150 | %idefine jge jge near | |
151 | %idefine jc jc near | |
152 | %idefine jnc jnc near | |
153 | %idefine js js near | |
154 | %idefine jns jns near | |
155 | ||
156 | %ifdef DOUBLE | |
157 | %idefine REAL QWORD | |
158 | %idefine DREAL dq | |
159 | %else | |
160 | %idefine REAL DWORD | |
161 | %idefine DREAL dd | |
162 | %endif | |
163 | ||
164 | ; Boolean truth values (same as those in debug.h) | |
165 | ||
166 | %idefine False 0 | |
167 | %idefine True 1 | |
168 | %idefine No 0 | |
169 | %idefine Yes 1 | |
170 | %idefine Yes 1 | |
171 | ||
172 | ; Macro to be invoked at the start of all modules to set up segments for | |
173 | ; later use. Does nothing for NASM. | |
174 | ||
175 | %imacro header 1 | |
176 | %endmacro | |
177 | ||
178 | ; Macro to begin a data segment | |
179 | ||
180 | %imacro begdataseg 1 | |
181 | %ifdef __GNUC__ | |
182 | segment .data public class=DATA use32 flat | |
183 | %else | |
184 | %ifdef flatmodel | |
185 | segment _DATA public align=4 class=DATA use32 flat | |
186 | %else | |
187 | segment _DATA public align=4 class=DATA use16 | |
188 | %endif | |
189 | %endif | |
190 | %endmacro | |
191 | ||
192 | ; Macro to end a data segment | |
193 | ||
194 | %imacro enddataseg 1 | |
195 | %endmacro | |
196 | ||
197 | ; Macro to begin a code segment | |
198 | ||
199 | %imacro begcodeseg 1 | |
200 | %ifdef __PIC__ | |
201 | %ifdef __LINUX__ | |
202 | extern _GLOBAL_OFFSET_TABLE_ | |
203 | %else | |
204 | extern __GLOBAL_OFFSET_TABLE_ | |
205 | %endif | |
206 | %endif | |
207 | %ifdef __GNUC__ | |
208 | segment .text public class=CODE use32 flat | |
209 | %else | |
210 | %ifdef flatmodel | |
211 | segment _TEXT public align=16 class=CODE use32 flat | |
212 | %else | |
213 | segment %1_TEXT public align=16 class=CODE use16 | |
214 | %endif | |
215 | %endif | |
216 | %endmacro | |
217 | ||
218 | ; Macro to begin a near code segment | |
219 | ||
220 | %imacro begcodeseg_near 0 | |
221 | %ifdef __GNUC__ | |
222 | segment .text public class=CODE use32 flat | |
223 | %else | |
224 | %ifdef flatmodel | |
225 | segment _TEXT public align=16 class=CODE use32 flat | |
226 | %else | |
227 | segment _TEXT public align=16 class=CODE use16 | |
228 | %endif | |
229 | %endif | |
230 | %endmacro | |
231 | ||
232 | ; Macro to end a code segment | |
233 | ||
234 | %imacro endcodeseg 1 | |
235 | %endmacro | |
236 | ||
237 | ; Macro to end a near code segment | |
238 | ||
239 | %imacro endcodeseg_near 0 | |
240 | %endmacro | |
241 | ||
242 | ; Macro for an extern C symbol. If the C compiler requires leading | |
243 | ; underscores, then the underscores are added to the symbol names, otherwise | |
244 | ; they are left off. The symbol name is referenced in the assembler code | |
245 | ; using the non-underscored symbol name. | |
246 | ||
247 | %imacro cextern 2 | |
248 | %ifdef __NOU_VAR__ | |
249 | extern %1 | |
250 | %else | |
251 | extern _%1 | |
252 | %define %1 _%1 | |
253 | %endif | |
254 | %endmacro | |
255 | ||
256 | %imacro cexternfunc 2 | |
257 | %ifdef __NOU__ | |
258 | extern %1 | |
259 | %else | |
260 | extern _%1 | |
261 | %define %1 _%1 | |
262 | %endif | |
263 | %endmacro | |
264 | ||
265 | ; Macro for a public C symbol. If the C compiler requires leading | |
266 | ; underscores, then the underscores are added to the symbol names, otherwise | |
267 | ; they are left off. The symbol name is referenced in the assembler code | |
268 | ; using the non-underscored symbol name. | |
269 | ||
270 | %imacro cpublic 1 | |
271 | %ifdef __NOU_VAR__ | |
272 | global %1 | |
273 | %1: | |
274 | %else | |
275 | global _%1 | |
276 | _%1: | |
277 | %define %1 _%1 | |
278 | %endif | |
279 | %endmacro | |
280 | ||
281 | ; Macro for an global C symbol. If the C compiler requires leading | |
282 | ; underscores, then the underscores are added to the symbol names, otherwise | |
283 | ; they are left off. The symbol name is referenced in the assembler code | |
284 | ; using the non-underscored symbol name. | |
285 | ||
286 | %imacro cglobal 1 | |
287 | %ifdef __NOU_VAR__ | |
288 | global %1 | |
289 | %else | |
290 | global _%1 | |
291 | %define %1 _%1 | |
292 | %endif | |
293 | %endmacro | |
294 | ||
295 | ; Macro for an global C function symbol. If the C compiler requires leading | |
296 | ; underscores, then the underscores are added to the symbol names, otherwise | |
297 | ; they are left off. The symbol name is referenced in the assembler code | |
298 | ; using the non-underscored symbol name. | |
299 | ||
300 | %imacro cglobalfunc 1 | |
301 | %ifdef __PIC__ | |
302 | global %1:function | |
303 | %else | |
304 | %ifdef __NOU__ | |
305 | global %1 | |
306 | %else | |
307 | global _%1 | |
308 | %define %1 _%1 | |
309 | %endif | |
310 | %endif | |
311 | %endmacro | |
312 | ||
313 | ; Macro to start a C callable function. This will be a far function for | |
314 | ; 16-bit code, and a near function for 32-bit code. | |
315 | ||
316 | %imacro cprocstatic 1 | |
317 | %push cproc | |
318 | %1: | |
319 | %ifdef flatmodel | |
320 | %stacksize flat | |
321 | %define ret retn | |
322 | %else | |
323 | %stacksize large | |
324 | %define ret retf | |
325 | %endif | |
326 | %assign %$localsize 0 | |
327 | %endmacro | |
328 | ||
329 | %imacro cprocstart 1 | |
330 | %push cproc | |
331 | cglobalfunc %1 | |
332 | %1: | |
333 | %ifdef flatmodel | |
334 | %stacksize flat | |
335 | %define ret retn | |
336 | %else | |
337 | %stacksize large | |
338 | %define ret retf | |
339 | %endif | |
340 | %assign %$localsize 0 | |
341 | %endmacro | |
342 | ||
343 | ; This macro sets up a procedure to be exported from a 16 bit DLL. Since the | |
344 | ; calling conventions are always _far _pascal for 16 bit DLL's, we actually | |
345 | ; rename this routine with an extra underscore with 'C' calling conventions | |
346 | ; and a small DLL stub will be provided by the high level code to call the | |
347 | ; assembler routine. | |
348 | ||
349 | %imacro cprocstartdll16 1 | |
350 | %ifdef __WINDOWS16__ | |
351 | cprocstart _%1 | |
352 | %else | |
353 | cprocstart %1 | |
354 | %endif | |
355 | %endmacro | |
356 | ||
357 | ; Macro to start a C callable near function. | |
358 | ||
359 | %imacro cprocnear 1 | |
360 | %push cproc | |
361 | cglobalfunc %1 | |
362 | %1: | |
363 | %define ret retn | |
364 | %ifdef flatmodel | |
365 | %stacksize flat | |
366 | %else | |
367 | %stacksize small | |
368 | %endif | |
369 | %assign %$localsize 0 | |
370 | %endmacro | |
371 | ||
372 | ; Macro to start a C callable far function. | |
373 | ||
374 | %imacro cprocfar 1 | |
375 | %push cproc | |
376 | cglobalfunc %1 | |
377 | %1: | |
378 | %define ret retf | |
379 | %ifdef flatmodel | |
380 | %stacksize flat | |
381 | %else | |
382 | %stacksize large | |
383 | %endif | |
384 | %assign %$localsize 0 | |
385 | %endmacro | |
386 | ||
387 | ; Macro to end a C function | |
388 | ||
389 | %imacro cprocend 0 | |
390 | %pop | |
391 | %endmacro | |
392 | ||
393 | ; Macros for entering and exiting C callable functions. Note that we must | |
394 | ; always save and restore the SI and DI registers for C functions, and for | |
395 | ; 32 bit C functions we also need to save and restore EBX and clear the | |
396 | ; direction flag. | |
397 | ||
398 | %imacro enter_c 0 | |
399 | push _bp | |
400 | mov _bp,_sp | |
401 | %ifnidn %$localsize,0 | |
402 | sub _sp,%$localsize | |
403 | %endif | |
404 | %ifdef flatmodel | |
405 | push ebx | |
406 | %endif | |
407 | push _si | |
408 | push _di | |
409 | %endmacro | |
410 | ||
411 | %imacro leave_c 0 | |
412 | pop _di | |
413 | pop _si | |
414 | %ifdef flatmodel | |
415 | pop ebx | |
416 | cld | |
417 | %endif | |
418 | %ifnidn %$localsize,0 | |
419 | mov _sp,_bp | |
420 | %endif | |
421 | pop _bp | |
422 | %endmacro | |
423 | ||
424 | %imacro use_ebx 0 | |
425 | %ifdef flatmodel | |
426 | push ebx | |
427 | %endif | |
428 | %endmacro | |
429 | ||
430 | %imacro unuse_ebx 0 | |
431 | %ifdef flatmodel | |
432 | pop ebx | |
433 | %endif | |
434 | %endmacro | |
435 | ||
436 | ; Macros for saving and restoring the value of DS,ES,FS,GS when it is to | |
437 | ; be used in assembly routines. This evaluates to nothing in the flat memory | |
438 | ; model, but is saves and restores DS in the large memory model. | |
439 | ||
440 | %imacro use_ds 0 | |
441 | %ifndef flatmodel | |
442 | push ds | |
443 | %endif | |
444 | %endmacro | |
445 | ||
446 | %imacro unuse_ds 0 | |
447 | %ifndef flatmodel | |
448 | pop ds | |
449 | %endif | |
450 | %endmacro | |
451 | ||
452 | %imacro use_es 0 | |
453 | %ifndef flatmodel | |
454 | push es | |
455 | %endif | |
456 | %endmacro | |
457 | ||
458 | %imacro unuse_es 0 | |
459 | %ifndef flatmodel | |
460 | pop es | |
461 | %endif | |
462 | %endmacro | |
463 | ||
464 | ; Macros for loading the address of a data pointer into a segment and | |
465 | ; index register pair. The %imacro explicitly loads DS or ES in the 16 bit | |
466 | ; memory model, or it simply loads the offset into the register in the flat | |
467 | ; memory model since DS and ES always point to all addressable memory. You | |
468 | ; must use the correct _REG (ie: _BX) %imacros for documentation purposes. | |
469 | ||
470 | %imacro _lds 2 | |
471 | %ifdef flatmodel | |
472 | mov %1,%2 | |
473 | %else | |
474 | lds %1,%2 | |
475 | %endif | |
476 | %endmacro | |
477 | ||
478 | %imacro _les 2 | |
479 | %ifdef flatmodel | |
480 | mov %1,%2 | |
481 | %else | |
482 | les %1,%2 | |
483 | %endif | |
484 | %endmacro | |
485 | ||
486 | ; Macros for adding and subtracting a value from registers. Two value are | |
487 | ; provided, one for 16 bit modes and another for 32 bit modes (the extended | |
488 | ; register is used in 32 bit modes). | |
489 | ||
490 | %imacro _add 3 | |
491 | %ifdef flatmodel | |
492 | add e%1, %3 | |
493 | %else | |
494 | add %1, %2 | |
495 | %endif | |
496 | %endmacro | |
497 | ||
498 | %imacro _sub 3 | |
499 | %ifdef flatmodel | |
500 | sub e%1, %3 | |
501 | %else | |
502 | sub %1, %2 | |
503 | %endif | |
504 | %endmacro | |
505 | ||
506 | ; Macro to clear the high order word for the 32 bit extended registers. | |
507 | ; This is used to convert an unsigned 16 bit value to an unsigned 32 bit | |
508 | ; value, and will evaluate to nothing in 16 bit modes. | |
509 | ||
510 | %imacro clrhi 1 | |
511 | %ifdef flatmodel | |
512 | movzx e%1,%1 | |
513 | %endif | |
514 | %endmacro | |
515 | ||
516 | %imacro sgnhi 1 | |
517 | %ifdef flatmodel | |
518 | movsx e%1,%1 | |
519 | %endif | |
520 | %endmacro | |
521 | ||
522 | ; Macro to load an extended register with an integer value in either mode | |
523 | ||
524 | %imacro loadint 2 | |
525 | %ifdef flatmodel | |
526 | mov e%1,%2 | |
527 | %else | |
528 | xor e%1,e%1 | |
529 | mov %1,%2 | |
530 | %endif | |
531 | %endmacro | |
532 | ||
533 | ; Macros to load and store integer values with string instructions | |
534 | ||
535 | %imacro LODSINT 0 | |
536 | %ifdef flatmodel | |
537 | lodsd | |
538 | %else | |
539 | lodsw | |
540 | %endif | |
541 | %endmacro | |
542 | ||
543 | %imacro STOSINT 0 | |
544 | %ifdef flatmodel | |
545 | stosd | |
546 | %else | |
547 | stosw | |
548 | %endif | |
549 | %endmacro | |
550 | ||
551 | ; Macros to provide resb, resw, resd compatibility with NASM | |
552 | ||
553 | %imacro dclb 1 | |
554 | times %1 db 0 | |
555 | %endmacro | |
556 | ||
557 | %imacro dclw 1 | |
558 | times %1 dw 0 | |
559 | %endmacro | |
560 | ||
561 | %imacro dcld 1 | |
562 | times %1 dd 0 | |
563 | %endmacro | |
564 | ||
565 | ; Macro to get the addres of the GOT for Linux/FreeBSD shared | |
566 | ; libraries into the EBX register. | |
567 | ||
568 | %imacro get_GOT 1 | |
569 | call %%getgot | |
570 | %%getgot: pop %1 | |
571 | add %1,_GLOBAL_OFFSET_TABLE_+$$-%%getgot wrt ..gotpc | |
572 | %endmacro | |
573 | ||
574 | ; Macro to get the address of a *local* variable that is global to | |
575 | ; a single module in a manner that will work correctly when compiled | |
576 | ; into a Linux shared library. Note that this will *not* work for | |
577 | ; variables that are defined as global to all modules. For that | |
578 | ; use the LEA_G macro | |
579 | ||
580 | %macro LEA_L 2 | |
581 | %ifdef __PIC__ | |
582 | get_GOT %1 | |
583 | lea %1,[%1+%2 wrt ..gotoff] | |
584 | %else | |
585 | lea %1,[%2] | |
586 | %endif | |
587 | %endmacro | |
588 | ||
589 | ; Same macro as above but for global variables public to *all* | |
590 | ; modules. | |
591 | ||
592 | %macro LEA_G 2 | |
593 | %ifdef __PIC__ | |
594 | get_GOT %1 | |
595 | mov %1,[%1+%2 wrt ..got] | |
596 | %else | |
597 | lea %1,[%2] | |
598 | %endif | |
599 | %endmacro | |
600 | ||
601 | ; macros to declare assembler function stubs for function structures | |
602 | ||
603 | %imacro BEGIN_STUBS_DEF 2 | |
604 | begdataseg _STUBS | |
605 | %ifdef __NOU_VAR__ | |
606 | extern %1 | |
607 | %define STUBS_START %1 | |
608 | %else | |
609 | extern _%1 | |
610 | %define STUBS_START _%1 | |
611 | %endif | |
612 | enddataseg _STUBS | |
613 | begcodeseg _STUBS | |
614 | %assign off %2 | |
615 | %endmacro | |
616 | ||
617 | %imacro DECLARE_STUB 1 | |
618 | %ifdef __PIC__ | |
619 | global %1:function | |
620 | %1: | |
621 | get_GOT eax | |
622 | mov eax,[eax+STUBS_START wrt ..got] | |
623 | jmp [eax+off] | |
624 | %else | |
625 | %ifdef __NOU__ | |
626 | global %1 | |
627 | %1: | |
628 | %else | |
629 | global _%1 | |
630 | _%1: | |
631 | %endif | |
632 | jmp [DWORD STUBS_START+off] | |
633 | %endif | |
634 | %assign off off+4 | |
635 | %endmacro | |
636 | ||
637 | %imacro SKIP_STUB 1 | |
638 | %assign off off+4 | |
639 | %endmacro | |
640 | ||
641 | %imacro DECLARE_STDCALL 2 | |
642 | %ifdef STDCALL_MANGLE | |
643 | global _%1@%2 | |
644 | _%1@%2: | |
645 | %else | |
646 | %ifdef STDCALL_USCORE | |
647 | global _%1 | |
648 | _%1: | |
649 | %else | |
650 | global %1 | |
651 | %1: | |
652 | %endif | |
653 | %endif | |
654 | jmp [DWORD STUBS_START+off] | |
655 | %assign off off+4 | |
656 | %endmacro | |
657 | ||
658 | %imacro END_STUBS_DEF 0 | |
659 | endcodeseg _STUBS | |
660 | %endmacro | |
661 | ||
662 | ; macros to declare assembler import stubs for binary loadable drivers | |
663 | ||
664 | %imacro BEGIN_IMPORTS_DEF 1 | |
665 | BEGIN_STUBS_DEF %1,4 | |
666 | %endmacro | |
667 | ||
668 | %imacro DECLARE_IMP 2 | |
669 | DECLARE_STUB %1 | |
670 | %endmacro | |
671 | ||
672 | %imacro SKIP_IMP 2 | |
673 | SKIP_STUB %1 | |
674 | %endmacro | |
675 | ||
676 | %imacro SKIP_IMP2 1 | |
677 | DECLARE_STUB %1 | |
678 | %endmacro | |
679 | ||
680 | %imacro SKIP_IMP3 1 | |
681 | SKIP_STUB %1 | |
682 | %endmacro | |
683 | ||
684 | %imacro END_IMPORTS_DEF 0 | |
685 | END_STUBS_DEF | |
686 | %endmacro | |
687 | ||
688 | else ; __NASM_MAJOR__ | |
689 | ||
690 | ;============================================================================ | |
691 | ; Macro package when compiling with TASM. | |
692 | ;============================================================================ | |
693 | ||
694 | ; Turn off underscores for globals if disabled for all externals | |
695 | ||
696 | ifdef __NOU__ | |
697 | __NOU_VAR__ = 1 | |
698 | endif | |
699 | ||
700 | ; Define the __WINDOWS__ symbol if we are compiling for any Windows | |
701 | ; environment | |
702 | ||
703 | ifdef __WINDOWS16__ | |
704 | __WINDOWS__ = 1 | |
705 | endif | |
706 | ifdef __WINDOWS32__ | |
707 | __WINDOWS__ = 1 | |
708 | __WINDOWS32_386__ = 1 | |
709 | endif | |
710 | ifdef __WIN386__ | |
711 | __WINDOWS__ = 1 | |
712 | __WINDOWS32_386__ = 1 | |
713 | endif | |
714 | ifdef __VXD__ | |
715 | __WINDOWS__ = 1 | |
716 | __WINDOWS32_386__ = 1 | |
717 | MASM | |
718 | .386 | |
719 | NO_SEGMENTS = 1 | |
720 | include vmm.inc ; IGNORE DEPEND | |
721 | include vsegment.inc ; IGNORE DEPEND | |
722 | IDEAL | |
723 | endif | |
724 | ||
725 | ; Macros for accessing 'generic' registers | |
726 | ||
727 | ifdef __FLAT__ | |
728 | _ax EQU eax ; EAX is used for accumulator | |
729 | _bx EQU ebx ; EBX is used for accumulator | |
730 | _cx EQU ecx ; ECX is used for looping | |
731 | _dx EQU edx ; EDX is used for data register | |
732 | _si EQU esi ; ESI is the source index register | |
733 | _di EQU edi ; EDI is the destination index register | |
734 | _bp EQU ebp ; EBP is used for base pointer register | |
735 | _sp EQU esp ; ESP is used for stack pointer register | |
736 | _es EQU ; ES and DS are the same in 32 bit PM | |
737 | typedef UCHAR BYTE ; Size of a character | |
738 | typedef USHORT WORD ; Size of a short | |
739 | typedef UINT DWORD ; Size of an integer | |
740 | typedef ULONG DWORD ; Size of a long | |
741 | typedef BOOL DWORD ; Size of a boolean | |
742 | typedef DPTR DWORD ; Size of a data pointer | |
743 | typedef FDPTR FWORD ; Size of a far data pointer | |
744 | typedef NDPTR DWORD ; Size of a near data pointer | |
745 | typedef CPTR DWORD ; Size of a code pointer | |
746 | typedef FCPTR FWORD ; Size of a far code pointer | |
747 | typedef NCPTR DWORD ; Size of a near code pointer | |
748 | typedef DUINT DWORD ; Declare a integer variable | |
749 | FPTR EQU NEAR ; Distance for function pointers | |
750 | intsize = 4 ; Size of an integer | |
751 | flatmodel = 1 ; This is a flat memory model | |
752 | P386 ; Turn on 386 code generation | |
753 | MODEL FLAT ; Set up for 32 bit simplified FLAT model | |
754 | else | |
755 | _ax EQU ax ; AX is used for accumulator | |
756 | _bx EQU bx ; BX is used for accumulator | |
757 | _cx EQU cx ; CX is used for looping | |
758 | _dx EQU dx ; DX is used for data register | |
759 | _si EQU si ; SI is the source index register | |
760 | _di EQU di ; DI is the destination index register | |
761 | _bp EQU bp ; BP is used for base pointer register | |
762 | _sp EQU sp ; SP is used for stack pointer register | |
763 | _es EQU es: ; ES is used for segment override | |
764 | typedef UCHAR BYTE ; Size of a character | |
765 | typedef USHORT WORD ; Size of a short | |
766 | typedef UINT WORD ; Size of an integer | |
767 | typedef ULONG DWORD ; Size of a long | |
768 | typedef BOOL WORD ; Size of a boolean | |
769 | typedef DPTR DWORD ; Size of a data pointer | |
770 | typedef FDPTR DWORD ; Size of a far data pointer | |
771 | typedef NDPTR WORD ; Size of a near data pointer | |
772 | typedef CPTR DWORD ; Size of a code pointer | |
773 | typedef FCPTR DWORD ; Size of a far code pointer | |
774 | typedef NCPTR WORD ; Size of a near code pointer | |
775 | typedef DUINT WORD ; Declare a integer variable | |
776 | FPTR EQU FAR ; Distance for function pointers | |
777 | intsize = 2 ; Size of an integer | |
778 | P386 ; Turn on 386 code generation | |
779 | endif | |
780 | invert EQU not | |
781 | ||
782 | ; Provide a typedef for real floating point numbers | |
783 | ||
784 | ifdef DOUBLE | |
785 | typedef REAL QWORD | |
786 | typedef DREAL QWORD | |
787 | else | |
788 | typedef REAL DWORD | |
789 | typedef DREAL DWORD | |
790 | endif | |
791 | ||
792 | ; Macros to access the floating point stack registers to convert them | |
793 | ; from NASM style to TASM style | |
794 | ||
795 | st0 EQU st(0) | |
796 | st1 EQU st(1) | |
797 | st2 EQU st(2) | |
798 | st3 EQU st(3) | |
799 | st4 EQU st(4) | |
800 | st5 EQU st(5) | |
801 | st6 EQU st(6) | |
802 | st7 EQU st(7) | |
803 | st8 EQU st(8) | |
804 | ||
805 | ; Boolean truth values (same as those in debug.h) | |
806 | ||
807 | ifndef __VXD__ | |
808 | False = 0 | |
809 | True = 1 | |
810 | No = 0 | |
811 | Yes = 1 | |
812 | Yes = 1 | |
813 | endif | |
814 | ||
815 | ; Macros for the _DATA data segment. This segment contains initialised data. | |
816 | ||
817 | MACRO begdataseg name | |
818 | ifdef __VXD__ | |
819 | MASM | |
820 | VXD_LOCKED_DATA_SEG | |
821 | IDEAL | |
822 | else | |
823 | ifdef flatmodel | |
824 | DATASEG | |
825 | else | |
826 | SEGMENT _DATA DWORD PUBLIC USE16 'DATA' | |
827 | endif | |
828 | endif | |
829 | ENDM | |
830 | ||
831 | MACRO enddataseg name | |
832 | ifdef __VXD__ | |
833 | MASM | |
834 | VXD_LOCKED_DATA_ENDS | |
835 | IDEAL | |
836 | else | |
837 | ifndef flatmodel | |
838 | ENDS _DATA | |
839 | endif | |
840 | endif | |
841 | ENDM | |
842 | ||
843 | ; Macro for the main code segment. | |
844 | ||
845 | MACRO begcodeseg name | |
846 | ifdef __VXD__ | |
847 | MASM | |
848 | VXD_LOCKED_CODE_SEG | |
849 | IDEAL | |
850 | else | |
851 | ifdef flatmodel | |
852 | CODESEG | |
853 | ASSUME CS:FLAT,DS:FLAT,SS:FLAT | |
854 | else | |
855 | SEGMENT &name&_TEXT PARA PUBLIC USE16 'CODE' | |
856 | ASSUME CS:&name&_TEXT,DS:_DATA | |
857 | endif | |
858 | endif | |
859 | ENDM | |
860 | ||
861 | ; Macro for a near code segment | |
862 | ||
863 | MACRO begcodeseg_near | |
864 | ifdef flatmodel | |
865 | CODESEG | |
866 | ASSUME CS:FLAT,DS:FLAT,SS:FLAT | |
867 | else | |
868 | SEGMENT _TEXT PARA PUBLIC USE16 'CODE' | |
869 | ASSUME CS:_TEXT,DS:_DATA | |
870 | endif | |
871 | ENDM | |
872 | ||
873 | MACRO endcodeseg name | |
874 | ifdef __VXD__ | |
875 | MASM | |
876 | VXD_LOCKED_CODE_ENDS | |
877 | IDEAL | |
878 | else | |
879 | ifndef flatmodel | |
880 | ENDS &name&_TEXT | |
881 | endif | |
882 | endif | |
883 | ENDM | |
884 | ||
885 | MACRO endcodeseg_near | |
886 | ifndef flatmodel | |
887 | ENDS _TEXT | |
888 | endif | |
889 | ENDM | |
890 | ||
891 | ; Macro to be invoked at the start of all modules to set up segments for | |
892 | ; later use. | |
893 | ||
894 | MACRO header name | |
895 | begdataseg name | |
896 | enddataseg name | |
897 | ENDM | |
898 | ||
899 | ; Macro for an extern C symbol. If the C compiler requires leading | |
900 | ; underscores, then the underscores are added to the symbol names, otherwise | |
901 | ; they are left off. The symbol name is referenced in the assembler code | |
902 | ; using the non-underscored symbol name. | |
903 | ||
904 | MACRO cextern name,size | |
905 | ifdef __NOU_VAR__ | |
906 | EXTRN name:size | |
907 | else | |
908 | EXTRN _&name&:size | |
909 | name EQU _&name& | |
910 | endif | |
911 | ENDM | |
912 | ||
913 | MACRO cexternfunc name,size | |
914 | ifdef __NOU__ | |
915 | EXTRN name:size | |
916 | else | |
917 | EXTRN _&name&:size | |
918 | name EQU _&name& | |
919 | endif | |
920 | ENDM | |
921 | ||
922 | MACRO stdexternfunc name,num_args,size | |
923 | ifdef STDCALL_MANGLE | |
924 | EXTRN _&name&@&num_args&:size | |
925 | name EQU _&name&@&num_args | |
926 | else | |
927 | EXTRN name:size | |
928 | endif | |
929 | ENDM | |
930 | ||
931 | ; Macro for a public C symbol. If the C compiler requires leading | |
932 | ; underscores, then the underscores are added to the symbol names, otherwise | |
933 | ; they are left off. The symbol name is referenced in the assembler code | |
934 | ; using the non-underscored symbol name. | |
935 | ||
936 | MACRO cpublic name | |
937 | ifdef __NOU_VAR__ | |
938 | name: | |
939 | PUBLIC name | |
940 | else | |
941 | _&name&: | |
942 | PUBLIC _&name& | |
943 | name EQU _&name& | |
944 | endif | |
945 | ENDM | |
946 | ||
947 | ; Macro for an global C symbol. If the C compiler requires leading | |
948 | ; underscores, then the underscores are added to the symbol names, otherwise | |
949 | ; they are left off. The symbol name is referenced in the assembler code | |
950 | ; using the non-underscored symbol name. | |
951 | ||
952 | MACRO cglobal name | |
953 | ifdef __NOU_VAR__ | |
954 | PUBLIC name | |
955 | else | |
956 | PUBLIC _&name& | |
957 | name EQU _&name& | |
958 | endif | |
959 | ENDM | |
960 | ||
961 | ; Macro for an global C function symbol. If the C compiler requires leading | |
962 | ; underscores, then the underscores are added to the symbol names, otherwise | |
963 | ; they are left off. The symbol name is referenced in the assembler code | |
964 | ; using the non-underscored symbol name. | |
965 | ||
966 | MACRO cglobalfunc name | |
967 | ifdef __NOU__ | |
968 | PUBLIC name | |
969 | else | |
970 | PUBLIC _&name& | |
971 | name EQU _&name& | |
972 | endif | |
973 | ENDM | |
974 | ||
975 | ; Macro to start a C callable function. This will be a far function for | |
976 | ; 16-bit code, and a near function for 32-bit code. | |
977 | ||
978 | MACRO cprocstatic name ; Set up model independant private proc | |
979 | ifdef flatmodel | |
980 | PROC name NEAR | |
981 | else | |
982 | PROC name FAR | |
983 | endif | |
984 | LocalSize = 0 | |
985 | ENDM | |
986 | ||
987 | MACRO cprocstart name ; Set up model independant proc | |
988 | ifdef flatmodel | |
989 | ifdef __NOU__ | |
990 | PROC name NEAR | |
991 | else | |
992 | PROC _&name& NEAR | |
993 | endif | |
994 | else | |
995 | ifdef __NOU__ | |
996 | PROC name FAR | |
997 | else | |
998 | PROC _&name& FAR | |
999 | endif | |
1000 | endif | |
1001 | LocalSize = 0 | |
1002 | cglobalfunc name | |
1003 | ENDM | |
1004 | ||
1005 | MACRO cprocnear name ; Set up near proc | |
1006 | ifdef __NOU__ | |
1007 | PROC name NEAR | |
1008 | else | |
1009 | PROC _&name& NEAR | |
1010 | endif | |
1011 | LocalSize = 0 | |
1012 | cglobalfunc name | |
1013 | ENDM | |
1014 | ||
1015 | MACRO cprocfar name ; Set up far proc | |
1016 | ifdef __NOU__ | |
1017 | PROC name FAR | |
1018 | else | |
1019 | PROC _&name& FAR | |
1020 | endif | |
1021 | LocalSize = 0 | |
1022 | cglobalfunc name | |
1023 | ENDM | |
1024 | ||
1025 | MACRO cprocend ; End procedure macro | |
1026 | ENDP | |
1027 | ENDM | |
1028 | ||
1029 | ; This macro sets up a procedure to be exported from a 16 bit DLL. Since the | |
1030 | ; calling conventions are always _far _pascal for 16 bit DLL's, we actually | |
1031 | ; rename this routine with an extra underscore with 'C' calling conventions | |
1032 | ; and a small DLL stub will be provided by the high level code to call the | |
1033 | ; assembler routine. | |
1034 | ||
1035 | MACRO cprocstartdll16 name | |
1036 | ifdef __WINDOWS16__ | |
1037 | cprocstart _&name& | |
1038 | else | |
1039 | cprocstart name | |
1040 | endif | |
1041 | ENDM | |
1042 | ||
1043 | ; Macros for entering and exiting C callable functions. Note that we must | |
1044 | ; always save and restore the SI and DI registers for C functions, and for | |
1045 | ; 32 bit C functions we also need to save and restore EBX and clear the | |
1046 | ; direction flag. | |
1047 | ||
1048 | MACRO save_c_regs | |
1049 | ifdef flatmodel | |
1050 | push ebx | |
1051 | endif | |
1052 | push _si | |
1053 | push _di | |
1054 | ENDM | |
1055 | ||
1056 | MACRO enter_c | |
1057 | push _bp | |
1058 | mov _bp,_sp | |
1059 | IFDIFI <LocalSize>,<0> | |
1060 | sub _sp,LocalSize | |
1061 | ENDIF | |
1062 | save_c_regs | |
1063 | ENDM | |
1064 | ||
1065 | MACRO restore_c_regs | |
1066 | pop _di | |
1067 | pop _si | |
1068 | ifdef flatmodel | |
1069 | pop ebx | |
1070 | endif | |
1071 | ENDM | |
1072 | ||
1073 | MACRO leave_c | |
1074 | restore_c_regs | |
1075 | cld | |
1076 | IFDIFI <LocalSize>,<0> | |
1077 | mov _sp,_bp | |
1078 | ENDIF | |
1079 | pop _bp | |
1080 | ENDM | |
1081 | ||
1082 | MACRO use_ebx | |
1083 | ifdef flatmodel | |
1084 | push ebx | |
1085 | endif | |
1086 | ENDM | |
1087 | ||
1088 | MACRO unuse_ebx | |
1089 | ifdef flatmodel | |
1090 | pop ebx | |
1091 | endif | |
1092 | ENDM | |
1093 | ||
1094 | ; Macros for saving and restoring the value of DS,ES,FS,GS when it is to | |
1095 | ; be used in assembly routines. This evaluates to nothing in the flat memory | |
1096 | ; model, but is saves and restores DS in the large memory model. | |
1097 | ||
1098 | MACRO use_ds | |
1099 | ifndef flatmodel | |
1100 | push ds | |
1101 | endif | |
1102 | ENDM | |
1103 | ||
1104 | MACRO unuse_ds | |
1105 | ifndef flatmodel | |
1106 | pop ds | |
1107 | endif | |
1108 | ENDM | |
1109 | ||
1110 | MACRO use_es | |
1111 | ifndef flatmodel | |
1112 | push es | |
1113 | endif | |
1114 | ENDM | |
1115 | ||
1116 | MACRO unuse_es | |
1117 | ifndef flatmodel | |
1118 | pop es | |
1119 | endif | |
1120 | ENDM | |
1121 | ||
1122 | ; Macros for loading the address of a data pointer into a segment and | |
1123 | ; index register pair. The macro explicitly loads DS or ES in the 16 bit | |
1124 | ; memory model, or it simply loads the offset into the register in the flat | |
1125 | ; memory model since DS and ES always point to all addressable memory. You | |
1126 | ; must use the correct _REG (ie: _BX) macros for documentation purposes. | |
1127 | ||
1128 | MACRO _lds reg, addr | |
1129 | ifdef flatmodel | |
1130 | mov reg,addr | |
1131 | else | |
1132 | lds reg,addr | |
1133 | endif | |
1134 | ENDM | |
1135 | ||
1136 | MACRO _les reg, addr | |
1137 | ifdef flatmodel | |
1138 | mov reg,addr | |
1139 | else | |
1140 | les reg,addr | |
1141 | endif | |
1142 | ENDM | |
1143 | ||
1144 | ; Macros for adding and subtracting a value from registers. Two value are | |
1145 | ; provided, one for 16 bit modes and another for 32 bit modes (the extended | |
1146 | ; register is used in 32 bit modes). | |
1147 | ||
1148 | MACRO _add reg, val16, val32 | |
1149 | ifdef flatmodel | |
1150 | add e®&, val32 | |
1151 | else | |
1152 | add reg, val16 | |
1153 | endif | |
1154 | ENDM | |
1155 | ||
1156 | MACRO _sub reg, val16, val32 | |
1157 | ifdef flatmodel | |
1158 | sub e®&, val32 | |
1159 | else | |
1160 | sub reg, val16 | |
1161 | endif | |
1162 | ENDM | |
1163 | ||
1164 | ; Macro to clear the high order word for the 32 bit extended registers. | |
1165 | ; This is used to convert an unsigned 16 bit value to an unsigned 32 bit | |
1166 | ; value, and will evaluate to nothing in 16 bit modes. | |
1167 | ||
1168 | MACRO clrhi reg | |
1169 | ifdef flatmodel | |
1170 | movzx e®&,reg | |
1171 | endif | |
1172 | ENDM | |
1173 | ||
1174 | MACRO sgnhi reg | |
1175 | ifdef flatmodel | |
1176 | movsx e®&,reg | |
1177 | endif | |
1178 | ENDM | |
1179 | ||
1180 | ; Macro to load an extended register with an integer value in either mode | |
1181 | ||
1182 | MACRO loadint reg,val | |
1183 | ifdef flatmodel | |
1184 | mov e®&,val | |
1185 | else | |
1186 | xor e®&,e®& | |
1187 | mov reg,val | |
1188 | endif | |
1189 | ENDM | |
1190 | ||
1191 | ; Macros to load and store integer values with string instructions | |
1192 | ||
1193 | MACRO LODSINT | |
1194 | ifdef flatmodel | |
1195 | lodsd | |
1196 | else | |
1197 | lodsw | |
1198 | endif | |
1199 | ENDM | |
1200 | ||
1201 | MACRO STOSINT | |
1202 | ifdef flatmodel | |
1203 | stosd | |
1204 | else | |
1205 | stosw | |
1206 | endif | |
1207 | ENDM | |
1208 | ||
1209 | ; Macros to provide resb, resw, resd compatibility with NASM | |
1210 | ||
1211 | MACRO dclb count | |
1212 | db count dup (0) | |
1213 | ENDM | |
1214 | ||
1215 | MACRO dclw count | |
1216 | dw count dup (0) | |
1217 | ENDM | |
1218 | ||
1219 | MACRO dcld count | |
1220 | dd count dup (0) | |
1221 | ENDM | |
1222 | ||
1223 | ; Macros to provide resb, resw, resd compatibility with NASM | |
1224 | ||
1225 | MACRO resb count | |
1226 | db count dup (?) | |
1227 | ENDM | |
1228 | ||
1229 | MACRO resw count | |
1230 | dw count dup (?) | |
1231 | ENDM | |
1232 | ||
1233 | MACRO resd count | |
1234 | dd count dup (?) | |
1235 | ENDM | |
1236 | ||
1237 | ; Macros to declare assembler stubs for function structures | |
1238 | ||
1239 | MACRO BEGIN_STUBS_DEF name, firstOffset | |
1240 | begdataseg _STUBS | |
1241 | ifdef __NOU_VAR__ | |
1242 | EXTRN name:DWORD | |
1243 | STUBS_START = name | |
1244 | else | |
1245 | EXTRN _&name&:DWORD | |
1246 | name EQU _&name& | |
1247 | STUBS_START = _&name | |
1248 | endif | |
1249 | enddataseg _STUBS | |
1250 | begcodeseg _STUBS | |
1251 | off = firstOffset | |
1252 | ENDM | |
1253 | ||
1254 | MACRO DECLARE_STUB name | |
1255 | ifdef __NOU__ | |
1256 | name: | |
1257 | PUBLIC name | |
1258 | else | |
1259 | _&name: | |
1260 | PUBLIC _&name | |
1261 | endif | |
1262 | jmp [DWORD STUBS_START+off] | |
1263 | off = off + 4 | |
1264 | ENDM | |
1265 | ||
1266 | MACRO SKIP_STUB name | |
1267 | off = off + 4 | |
1268 | ENDM | |
1269 | ||
1270 | MACRO DECLARE_STDCALL name,num_args | |
1271 | ifdef STDCALL_MANGLE | |
1272 | _&name&@&num_args&: | |
1273 | PUBLIC _&name&@&num_args& | |
1274 | else | |
1275 | name: | |
1276 | PUBLIC name | |
1277 | endif | |
1278 | jmp [DWORD STUBS_START+off] | |
1279 | off = off + 4 | |
1280 | ENDM | |
1281 | ||
1282 | MACRO END_STUBS_DEF | |
1283 | endcodeseg _STUBS | |
1284 | ENDM | |
1285 | ||
1286 | MACRO BEGIN_IMPORTS_DEF name | |
1287 | BEGIN_STUBS_DEF name,4 | |
1288 | ENDM | |
1289 | ||
1290 | ifndef LOCAL_DECLARE_IMP | |
1291 | MACRO DECLARE_IMP name, numArgs | |
1292 | DECLARE_STUB name | |
1293 | ENDM | |
1294 | ||
1295 | MACRO SKIP_IMP name | |
1296 | SKIP_STUB name | |
1297 | ENDM | |
1298 | ||
1299 | MACRO SKIP_IMP2 name, numArgs | |
1300 | DECLARE_STUB name | |
1301 | ENDM | |
1302 | ||
1303 | MACRO SKIP_IMP3 name | |
1304 | SKIP_STUB name | |
1305 | ENDM | |
1306 | endif | |
1307 | ||
1308 | MACRO END_IMPORTS_DEF | |
1309 | END_STUBS_DEF | |
1310 | ENDM | |
1311 | ||
1312 | MACRO LEA_L reg,name | |
1313 | lea reg,[name] | |
1314 | ENDM | |
1315 | ||
1316 | MACRO LEA_G reg,name | |
1317 | lea reg,[name] | |
1318 | ENDM | |
1319 | ||
1320 | endif | |
1321 |