preproc: Fix nil dereference on error paths
[nasm.git] / misc / scitech.mac
blob26f85f496153fbba8dc4b8cb2b2e1293f90684bb
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.
15 ;*    The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
17 ;*    The Initial Developer of the Original Code is SciTech Software, Inc.
18 ;*    All Rights Reserved.
20 ;*  ========================================================================
22 ;* Language:    NetWide Assembler (NASM) or Turbo Assembler (TASM)
23 ;* Environment: Any Intel Environment
25 ;* Description: Macros to provide memory model independant assembly language
26 ;*              module for C programming. Supports the large and flat memory
27 ;*                              models.
29 ;*              The defines that you should use when assembling modules that
30 ;*                              use this macro package are:
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
37 ;*                              The default settings are for 16-bit large memory model with
38 ;*                              leading underscores for symbol names.
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).
48 ;****************************************************************************
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.
56 ifdef __NASM_MAJOR__
58 ;============================================================================
59 ; Macro package when compiling with NASM.
60 ;============================================================================
62 ; Turn off underscores for globals if disabled for all externals
64 %ifdef  __NOU__
65 %define __NOU_VAR__
66 %endif
68 ; Define the __WINDOWS__ symbol if we are compiling for any Windows
69 ; environment
71 %ifdef  __WINDOWS16__
72 %define __WINDOWS__                     1
73 %endif
74 %ifdef  __WINDOWS32__
75 %define __WINDOWS__                     1
76 %define __WINDOWS32_386__       1
77 %endif
79 ; Macros for accessing 'generic' registers
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
135 ; Convert all jumps to near jumps, since NASM does not so this automatically
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
156 %ifdef  DOUBLE
157 %idefine        REAL    QWORD
158 %idefine        DREAL   dq
159 %else
160 %idefine        REAL    DWORD
161 %idefine        DREAL   dd
162 %endif
164 ; Boolean truth values (same as those in debug.h)
166 %idefine False          0
167 %idefine True           1
168 %idefine No                     0
169 %idefine Yes            1
170 %idefine Yes            1
172 ; Macro to be invoked at the start of all modules to set up segments for
173 ; later use. Does nothing for NASM.
175 %imacro header 1
176 %endmacro
178 ; Macro to begin a data segment
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
192 ; Macro to end a data segment
194 %imacro enddataseg 1
195 %endmacro
197 ; Macro to begin a code segment
199 %imacro begcodeseg 1
200 %ifdef __GNUC__
201 segment .text public class=CODE use32 flat
202 %else
203 %ifdef flatmodel
204 segment _TEXT public align=16 class=CODE use32 flat
205 %else
206 segment %1_TEXT public align=16 class=CODE use16
207 %endif
208 %endif
209 %endmacro
211 ; Macro to begin a near code segment
213 %imacro begcodeseg_near 0
214 %ifdef __GNUC__
215 segment .text public class=CODE use32 flat
216 %else
217 %ifdef flatmodel
218 segment _TEXT public align=16 class=CODE use32 flat
219 %else
220 segment _TEXT public align=16 class=CODE use16
221 %endif
222 %endif
223 %endmacro
225 ; Macro to end a code segment
227 %imacro endcodeseg 1
228 %endmacro
230 ; Macro to end a near code segment
232 %imacro endcodeseg_near 0
233 %endmacro
235 ; Macro for an extern C symbol. If the C compiler requires leading
236 ; underscores, then the underscores are added to the symbol names, otherwise
237 ; they are left off. The symbol name is referenced in the assembler code
238 ; using the non-underscored symbol name.
240 %imacro cextern 2
241 %ifdef  __NOU_VAR__
242 extern %1
243 %else
244 extern _%1
245 %define %1 _%1
246 %endif
247 %endmacro
249 %imacro cexternfunc 2
250 %ifdef  __NOU__
251 extern %1
252 %else
253 extern _%1
254 %define %1 _%1
255 %endif
256 %endmacro
258 ; Macro for a public C symbol. If the C compiler requires leading
259 ; underscores, then the underscores are added to the symbol names, otherwise
260 ; they are left off. The symbol name is referenced in the assembler code
261 ; using the non-underscored symbol name.
263 %imacro cpublic 1
264 %ifdef  __NOU_VAR__
265 global %1
267 %else
268 global _%1
269 _%1:
270 %define %1 _%1
271 %endif
272 %endmacro
274 ; Macro for an global C symbol. If the C compiler requires leading
275 ; underscores, then the underscores are added to the symbol names, otherwise
276 ; they are left off. The symbol name is referenced in the assembler code
277 ; using the non-underscored symbol name.
279 %imacro cglobal 1
280 %ifdef  __NOU_VAR__
281 global %1
282 %else
283 global _%1
284 %define %1 _%1
285 %endif
286 %endmacro
288 ; Macro for an global C function symbol. If the C compiler requires leading
289 ; underscores, then the underscores are added to the symbol names, otherwise
290 ; they are left off. The symbol name is referenced in the assembler code
291 ; using the non-underscored symbol name.
293 %imacro cglobalfunc 1
294 %ifdef  __NOU__
295 global %1
296 %else
297 global _%1
298 %define %1 _%1
299 %endif
300 %endmacro
302 ; Macro to start a C callable function. This will be a far function for
303 ; 16-bit code, and a near function for 32-bit code.
305 %imacro cprocstatic 1
306 %push cproc
308 %ifdef flatmodel
309 %stacksize flat
310 %define ret     retn
311 %else
312 %stacksize large
313 %define ret     retf
314 %endif
315 %assign %$localsize 0
316 %endmacro
318 %imacro cprocstart 1
319 %push cproc
320         cglobalfunc %1
322 %ifdef flatmodel
323 %stacksize flat
324 %define ret     retn
325 %else
326 %stacksize large
327 %define ret     retf
328 %endif
329 %assign %$localsize 0
330 %endmacro
332 ; This macro sets up a procedure to be exported from a 16 bit DLL. Since the
333 ; calling conventions are always _far _pascal for 16 bit DLL's, we actually
334 ; rename this routine with an extra underscore with 'C' calling conventions
335 ; and a small DLL stub will be provided by the high level code to call the
336 ; assembler routine.
338 %imacro cprocstartdll16 1
339 %ifdef  __WINDOWS16__
340 cprocstart      _%1
341 %else
342 cprocstart      %1
343 %endif
344 %endmacro
346 ; Macro to start a C callable near function.
348 %imacro cprocnear 1
349 %push cproc
350         cglobalfunc %1
352 %define ret     retn
353 %ifdef flatmodel
354 %stacksize flat
355 %else
356 %stacksize small
357 %endif
358 %assign %$localsize 0
359 %endmacro
361 ; Macro to start a C callable far function.
363 %imacro cprocfar 1
364 %push cproc
365         cglobalfunc %1
367 %define ret     retf
368 %ifdef flatmodel
369 %stacksize flat
370 %else
371 %stacksize large
372 %endif
373 %assign %$localsize 0
374 %endmacro
376 ; Macro to end a C function
378 %imacro cprocend 0
379 %pop
380 %endmacro
382 ; Macros for entering and exiting C callable functions. Note that we must
383 ; always save and restore the SI and DI registers for C functions, and for
384 ; 32 bit C functions we also need to save and restore EBX and clear the
385 ; direction flag.
387 %imacro enter_c 0
388                 push    _bp
389                 mov     _bp,_sp
390 %ifnidn %$localsize,0
391                 sub             _sp,%$localsize
392 %endif
393 %ifdef  flatmodel
394                 push    ebx
395 %endif
396                 push    _si
397                 push    _di
398 %endmacro
400 %imacro leave_c 0
401                 pop             _di
402                 pop             _si
403 %ifdef  flatmodel
404                 pop             ebx
405                 cld
406 %endif
407 %ifnidn %$localsize,0
408                 mov     _sp,_bp
409 %endif
410                 pop     _bp
411 %endmacro
413 %imacro   use_ebx 0
414 %ifdef flatmodel
415                 push    ebx
416 %endif
417 %endmacro
419 %imacro   unuse_ebx 0
420 %ifdef flatmodel
421                 pop     ebx
422 %endif
423 %endmacro
425 ; Macros for saving and restoring the value of DS,ES,FS,GS when it is to
426 ; be used in assembly routines. This evaluates to nothing in the flat memory
427 ; model, but is saves and restores DS in the large memory model.
429 %imacro use_ds 0
430 %ifndef flatmodel
431                 push    ds
432 %endif
433 %endmacro
435 %imacro unuse_ds 0
436 %ifndef flatmodel
437                 pop             ds
438 %endif
439 %endmacro
441 %imacro use_es 0
442 %ifndef flatmodel
443                 push    es
444 %endif
445 %endmacro
447 %imacro unuse_es 0
448 %ifndef flatmodel
449                 pop             es
450 %endif
451 %endmacro
453 ; Macros for loading the address of a data pointer into a segment and
454 ; index register pair. The %imacro explicitly loads DS or ES in the 16 bit
455 ; memory model, or it simply loads the offset into the register in the flat
456 ; memory model since DS and ES always point to all addressable memory. You
457 ; must use the correct _REG (ie: _BX) %imacros for documentation purposes.
459 %imacro _lds    2
460 %ifdef flatmodel
461                 mov     %1,%2
462 %else
463                 lds             %1,%2
464 %endif
465 %endmacro
467 %imacro   _les  2
468 %ifdef flatmodel
469                 mov     %1,%2
470 %else
471                 les             %1,%2
472 %endif
473 %endmacro
475 ; Macros for adding and subtracting a value from registers. Two value are
476 ; provided, one for 16 bit modes and another for 32 bit modes (the extended
477 ; register is used in 32 bit modes).
479 %imacro   _add  3
480 %ifdef flatmodel
481                 add             e%1, %3
482 %else
483                 add             %1, %2
484 %endif
485 %endmacro
487 %imacro _sub    3
488 %ifdef flatmodel
489                 sub             e%1, %3
490 %else
491                 sub             %1, %2
492 %endif
493 %endmacro
495 ; Macro to clear the high order word for the 32 bit extended registers.
496 ; This is used to convert an unsigned 16 bit value to an unsigned 32 bit
497 ; value, and will evaluate to nothing in 16 bit modes.
499 %imacro clrhi   1
500 %ifdef  flatmodel
501                 movzx   e%1,%1
502 %endif
503 %endmacro
505 %imacro sgnhi   1
506 %ifdef  flatmodel
507                 movsx   e%1,%1
508 %endif
509 %endmacro
511 ; Macro to load an extended register with an integer value in either mode
513 %imacro loadint 2
514 %ifdef flatmodel
515                 mov             e%1,%2
516 %else
517                 xor             e%1,e%1
518                 mov     %1,%2
519 %endif
520 %endmacro
522 ; Macros to load and store integer values with string instructions
524 %imacro LODSINT 0
525 %ifdef flatmodel
526                 lodsd
527 %else
528                 lodsw
529 %endif
530 %endmacro
532 %imacro STOSINT 0
533 %ifdef flatmodel
534                 stosd
535 %else
536                 stosw
537 %endif
538 %endmacro
540 ; Macros to provide resb, resw, resd compatibility with NASM
542 %imacro dclb 1
543 times %1 db 0
544 %endmacro
546 %imacro dclw 1
547 times %1 dw 0
548 %endmacro
550 %imacro dcld 1
551 times %1 dd 0
552 %endmacro
554 ; macros to declare assembler function stubs for function structures
556 %imacro BEGIN_STUBS_DEF 2
557 begdataseg  _STUBS
558 %ifdef  __NOU_VAR__
559 extern %1
560 %define STUBS_START     %1
561 %else
562 extern _%1
563 %define STUBS_START     _%1
564 %endif
565 enddataseg  _STUBS
566 begcodeseg  _STUBS
567 %assign off %2
568 %endmacro
570 %imacro   DECLARE_STUB  1
571 %ifdef  __NOU__
572                 global %1
574 %else
575                 global _%1
576 _%1:
577 %endif
578                 jmp     [DWORD STUBS_START+off]
579 %assign off off+4
580 %endmacro
582 %imacro DECLARE_STDCALL 2
583 %ifdef  STDCALL_MANGLE
584                 global _%1@%2
585 _%1@%2:
586 %else
587 %ifdef __GNUC__
588                 global _%1
589 _%1:
590 %else
591                 global %1
593 %endif
594 %endif
595                 jmp     [DWORD STUBS_START+off]
596 %assign off off+4
597 %endmacro
599 %imacro   END_STUBS_DEF 0
600 endcodeseg  _STUBS
601 %endmacro
603 ; macros to declare assembler import stubs for binary loadable drivers
605 %imacro BEGIN_IMPORTS_DEF       1
606 BEGIN_STUBS_DEF %1,4
607 %endmacro
609 %imacro   DECLARE_IMP   1
610 DECLARE_STUB    %1
611 %endmacro
613 %imacro   END_IMPORTS_DEF 0
614 END_STUBS_DEF
615 %endmacro
617 else    ; __NASM_MAJOR__
619 ;============================================================================
620 ; Macro package when compiling with TASM.
621 ;============================================================================
623 ; Turn off underscores for globals if disabled for all externals
625 ifdef   __NOU__
626 __NOU_VAR__                     = 1
627 endif
629 ; Define the __WINDOWS__ symbol if we are compiling for any Windows
630 ; environment
632 ifdef   __WINDOWS16__
633 __WINDOWS__             = 1
634 endif
635 ifdef   __WINDOWS32__
636 __WINDOWS__             = 1
637 __WINDOWS32_386__       = 1
638 endif
639 ifdef   __WIN386__
640 __WINDOWS__             = 1
641 __WINDOWS32_386__       = 1
642 endif
643 ifdef   __VXD__
644 __WINDOWS__             = 1
645 __WINDOWS32_386__       = 1
646                 MASM
647                 .386
648                 NO_SEGMENTS     = 1
649                 include vmm.inc                 ; IGNORE DEPEND
650                 include vsegment.inc    ; IGNORE DEPEND
651                 IDEAL
652 endif
654 ; Macros for accessing 'generic' registers
656 ifdef   __FLAT__
657                 _ax                     EQU     eax             ; EAX is used for accumulator
658                 _bx                     EQU     ebx             ; EBX is used for accumulator
659                 _cx             EQU ecx     ; ECX is used for looping
660                 _dx                     EQU     edx             ; EDX is used for data register
661                 _si                     EQU     esi             ; ESI is the source index register
662                 _di                     EQU     edi             ; EDI is the destination index register
663                 _bp                     EQU     ebp             ; EBP is used for base pointer register
664                 _sp                     EQU     esp             ; ESP is used for stack pointer register
665                 _es                     EQU                     ; ES and DS are the same in 32 bit PM
666                 typedef UCHAR BYTE              ; Size of a character
667                 typedef USHORT WORD             ; Size of a short
668                 typedef UINT DWORD              ; Size of an integer
669                 typedef ULONG DWORD             ; Size of a long
670                 typedef BOOL DWORD      ; Size of a boolean
671                 typedef DPTR DWORD              ; Size of a data pointer
672                 typedef FDPTR FWORD             ; Size of a far data pointer
673                 typedef NDPTR DWORD             ; Size of a near data pointer
674                 typedef CPTR DWORD              ; Size of a code pointer
675                 typedef FCPTR FWORD             ; Size of a far code pointer
676                 typedef NCPTR DWORD             ; Size of a near code pointer
677                 typedef DUINT DWORD             ; Declare a integer variable
678                 FPTR        EQU NEAR    ; Distance for function pointers
679                 intsize         =       4               ; Size of an integer
680                 flatmodel       =       1               ; This is a flat memory model
681                 P386                    ; Turn on 386 code generation
682                 MODEL       FLAT        ; Set up for 32 bit simplified FLAT model
683 else
684                 _ax                     EQU     ax              ; AX is used for accumulator
685                 _bx                     EQU     bx              ; BX is used for accumulator
686                 _cx             EQU cx          ; CX is used for looping
687                 _dx                     EQU     dx              ; DX is used for data register
688                 _si                     EQU     si              ; SI is the source index register
689                 _di                     EQU     di              ; DI is the destination index register
690                 _bp                     EQU     bp              ; BP is used for base pointer register
691                 _sp                     EQU     sp              ; SP is used for stack pointer register
692                 _es                     EQU es:         ; ES is used for segment override
693                 typedef UCHAR BYTE      ; Size of a character
694                 typedef USHORT WORD             ; Size of a short
695                 typedef UINT WORD               ; Size of an integer
696                 typedef ULONG DWORD             ; Size of a long
697                 typedef BOOL WORD               ; Size of a boolean
698                 typedef DPTR DWORD              ; Size of a data pointer
699                 typedef FDPTR DWORD             ; Size of a far data pointer
700                 typedef NDPTR WORD              ; Size of a near data pointer
701                 typedef CPTR DWORD              ; Size of a code pointer
702                 typedef FCPTR DWORD             ; Size of a far code pointer
703                 typedef NCPTR WORD              ; Size of a near code pointer
704                 typedef DUINT WORD              ; Declare a integer variable
705                 FPTR        EQU FAR             ; Distance for function pointers
706                 intsize         =       2               ; Size of an integer
707                 P386                                    ; Turn on 386 code generation
708 endif
709         invert      EQU not
711 ; Provide a typedef for real floating point numbers
713 ifdef   DOUBLE
714 typedef REAL    QWORD
715 typedef DREAL   QWORD
716 else
717 typedef REAL    DWORD
718 typedef DREAL   DWORD
719 endif
721 ; Macros to access the floating point stack registers to convert them
722 ; from NASM style to TASM style
724 st0                     EQU             st(0)
725 st1                     EQU             st(1)
726 st2                     EQU             st(2)
727 st3                     EQU             st(3)
728 st4                     EQU             st(4)
729 st5                     EQU             st(5)
730 st6                     EQU             st(6)
731 st7                     EQU             st(7)
732 st8                     EQU             st(8)
734 ; Boolean truth values (same as those in debug.h)
736 ifndef  __VXD__
737 False           =               0
738 True            =               1
739 No                      =               0
740 Yes                     =               1
741 Yes                     =               1
742 endif
744 ; Macros for the _DATA data segment. This segment contains initialised data.
746 MACRO   begdataseg name
747 ifdef   __VXD__
748                 MASM
749 VXD_LOCKED_DATA_SEG
750                 IDEAL
751 else
752 ifdef   flatmodel
753                 DATASEG
754 else
755 SEGMENT _DATA DWORD PUBLIC USE16 'DATA'
756 endif
757 endif
758 ENDM
760 MACRO   enddataseg name
761 ifdef   __VXD__
762                 MASM
763 VXD_LOCKED_DATA_ENDS
764                 IDEAL
765 else
766 ifndef  flatmodel
767 ENDS    _DATA
768 endif
769 endif
770 ENDM
772 ; Macro for the main code segment.
774 MACRO   begcodeseg name
775 ifdef   __VXD__
776                 MASM
777 VXD_LOCKED_CODE_SEG
778                 IDEAL
779 else
780 ifdef   flatmodel
781                 CODESEG
782                 ASSUME  CS:FLAT,DS:FLAT,SS:FLAT
783 else
784 SEGMENT &name&_TEXT PARA PUBLIC USE16 'CODE'
785                 ASSUME CS:&name&_TEXT,DS:_DATA
786 endif
787 endif
788 ENDM
790 ; Macro for a near code segment
792 MACRO   begcodeseg_near
793 ifdef   flatmodel
794                 CODESEG
795                 ASSUME  CS:FLAT,DS:FLAT,SS:FLAT
796 else
797 SEGMENT _TEXT PARA PUBLIC USE16 'CODE'
798                 ASSUME CS:_TEXT,DS:_DATA
799 endif
800 ENDM
802 MACRO   endcodeseg name
803 ifdef   __VXD__
804                 MASM
805 VXD_LOCKED_CODE_ENDS
806                 IDEAL
807 else
808 ifndef  flatmodel
809 ENDS    &name&_TEXT
810 endif
811 endif
812 ENDM
814 MACRO   endcodeseg_near
815 ifndef  flatmodel
816 ENDS    _TEXT
817 endif
818 ENDM
820 ; Macro to be invoked at the start of all modules to set up segments for
821 ; later use.
823 MACRO   header name
824 begdataseg name
825 enddataseg name
826 ENDM
828 ; Macro for an extern C symbol. If the C compiler requires leading
829 ; underscores, then the underscores are added to the symbol names, otherwise
830 ; they are left off. The symbol name is referenced in the assembler code
831 ; using the non-underscored symbol name.
833 MACRO   cextern name,size
834 ifdef   __NOU_VAR__
835                 EXTRN   name:size
836 else
837                 EXTRN   _&name&:size
838 name    EQU             _&name&
839 endif
840 ENDM
842 MACRO   cexternfunc     name,size
843 ifdef   __NOU__
844                 EXTRN   name:size
845 else
846                 EXTRN   _&name&:size
847 name    EQU             _&name&
848 endif
849 ENDM
851 MACRO   stdexternfunc   name,args,size
852 ifdef   STDCALL_MANGLE
853                 EXTRN   _&name&@&num_args&:size
854 name    EQU             _&name&@&num_args
855 else
856                 EXTRN   name:size
857 endif
858 ENDM
860 ; Macro for a public C symbol. If the C compiler requires leading
861 ; underscores, then the underscores are added to the symbol names, otherwise
862 ; they are left off. The symbol name is referenced in the assembler code
863 ; using the non-underscored symbol name.
865 MACRO   cpublic name
866 ifdef   __NOU_VAR__
867 name:
868                 PUBLIC  name
869 else
870 _&name&:
871                 PUBLIC  _&name&
872 name    EQU             _&name&
873 endif
874 ENDM
876 ; Macro for an global C symbol. If the C compiler requires leading
877 ; underscores, then the underscores are added to the symbol names, otherwise
878 ; they are left off. The symbol name is referenced in the assembler code
879 ; using the non-underscored symbol name.
881 MACRO   cglobal name
882 ifdef   __NOU_VAR__
883                 PUBLIC  name
884 else
885                 PUBLIC  _&name&
886 name    EQU             _&name&
887 endif
888 ENDM
890 ; Macro for an global C function symbol. If the C compiler requires leading
891 ; underscores, then the underscores are added to the symbol names, otherwise
892 ; they are left off. The symbol name is referenced in the assembler code
893 ; using the non-underscored symbol name.
895 MACRO   cglobalfunc name
896 ifdef   __NOU__
897                 PUBLIC  name
898 else
899                 PUBLIC  _&name&
900 name    EQU             _&name&
901 endif
902 ENDM
904 ; Macro to start a C callable function. This will be a far function for
905 ; 16-bit code, and a near function for 32-bit code.
907 MACRO   cprocstatic name        ; Set up model independant private proc
908 ifdef flatmodel
909 PROC    name NEAR
910 else
911 PROC    name FAR
912 endif
913 LocalSize       = 0
914 ENDM
916 MACRO   cprocstart name         ; Set up model independant proc
917 ifdef flatmodel
918 ifdef   __NOU__
919 PROC    name NEAR
920 else
921 PROC    _&name& NEAR
922 endif
923 else
924 ifdef   __NOU__
925 PROC    name FAR
926 else
927 PROC    _&name& FAR
928 endif
929 endif
930 LocalSize       = 0
931                 cglobalfunc     name
932 ENDM
934 MACRO   cprocnear name          ; Set up near proc
935 ifdef   __NOU__
936 PROC    name NEAR
937 else
938 PROC    _&name& NEAR
939 endif
940 LocalSize       = 0
941                 cglobalfunc     name
942 ENDM
944 MACRO   cprocfar name           ; Set up far proc
945 ifdef   __NOU__
946 PROC    name FAR
947 else
948 PROC    _&name& FAR
949 endif
950 LocalSize       = 0
951                 cglobalfunc     name
952 ENDM
954 MACRO   cprocend                   ; End procedure macro
955 ENDP
956 ENDM
958 ; This macro sets up a procedure to be exported from a 16 bit DLL. Since the
959 ; calling conventions are always _far _pascal for 16 bit DLL's, we actually
960 ; rename this routine with an extra underscore with 'C' calling conventions
961 ; and a small DLL stub will be provided by the high level code to call the
962 ; assembler routine.
964 MACRO   cprocstartdll16 name
965 ifdef   __WINDOWS16__
966 cprocstart      _&name&
967 else
968 cprocstart      name
969 endif
970 ENDM
972 ; Macros for entering and exiting C callable functions. Note that we must
973 ; always save and restore the SI and DI registers for C functions, and for
974 ; 32 bit C functions we also need to save and restore EBX and clear the
975 ; direction flag.
977 MACRO   save_c_regs
978 ifdef   flatmodel
979                 push    ebx
980 endif
981                 push    _si
982                 push    _di
983 ENDM
985 MACRO   enter_c
986                 push    _bp
987                 mov     _bp,_sp
988         IFDIFI  <LocalSize>,<0>
989                 sub             _sp,LocalSize
990         ENDIF
991                 save_c_regs
992 ENDM
994 MACRO   restore_c_regs
995                 pop             _di
996                 pop             _si
997 ifdef   flatmodel
998                 pop             ebx
999 endif
1000 ENDM
1002 MACRO   leave_c
1003                 restore_c_regs
1004                 cld
1005         IFDIFI  <LocalSize>,<0>
1006                 mov     _sp,_bp
1007         ENDIF
1008                 pop     _bp
1009 ENDM
1011 MACRO   use_ebx
1012 ifdef flatmodel
1013                 push    ebx
1014 endif
1015 ENDM
1017 MACRO   unuse_ebx
1018 ifdef flatmodel
1019                 pop     ebx
1020 endif
1021 ENDM
1023 ; Macros for saving and restoring the value of DS,ES,FS,GS when it is to
1024 ; be used in assembly routines. This evaluates to nothing in the flat memory
1025 ; model, but is saves and restores DS in the large memory model.
1027 MACRO   use_ds
1028 ifndef flatmodel
1029                 push    ds
1030 endif
1031 ENDM
1033 MACRO   unuse_ds
1034 ifndef flatmodel
1035                 pop             ds
1036 endif
1037 ENDM
1039 MACRO   use_es
1040 ifndef flatmodel
1041                 push    es
1042 endif
1043 ENDM
1045 MACRO   unuse_es
1046 ifndef flatmodel
1047                 pop             es
1048 endif
1049 ENDM
1051 ; Macros for loading the address of a data pointer into a segment and
1052 ; index register pair. The macro explicitly loads DS or ES in the 16 bit
1053 ; memory model, or it simply loads the offset into the register in the flat
1054 ; memory model since DS and ES always point to all addressable memory. You
1055 ; must use the correct _REG (ie: _BX) macros for documentation purposes.
1057 MACRO   _lds    reg, addr
1058 ifdef flatmodel
1059                 mov     reg,addr
1060 else
1061                 lds             reg,addr
1062 endif
1063 ENDM
1065 MACRO   _les    reg, addr
1066 ifdef flatmodel
1067                 mov     reg,addr
1068 else
1069                 les             reg,addr
1070 endif
1071 ENDM
1073 ; Macros for adding and subtracting a value from registers. Two value are
1074 ; provided, one for 16 bit modes and another for 32 bit modes (the extended
1075 ; register is used in 32 bit modes).
1077 MACRO   _add    reg, val16, val32
1078 ifdef flatmodel
1079                 add             e&reg&, val32
1080 else
1081                 add             reg, val16
1082 endif
1083 ENDM
1085 MACRO   _sub    reg, val16, val32
1086 ifdef flatmodel
1087                 sub             e&reg&, val32
1088 else
1089                 sub             reg, val16
1090 endif
1091 ENDM
1093 ; Macro to clear the high order word for the 32 bit extended registers.
1094 ; This is used to convert an unsigned 16 bit value to an unsigned 32 bit
1095 ; value, and will evaluate to nothing in 16 bit modes.
1097 MACRO   clrhi   reg
1098 ifdef   flatmodel
1099                 movzx   e&reg&,reg
1100 endif
1101 ENDM
1103 MACRO   sgnhi   reg
1104 ifdef   flatmodel
1105                 movsx   e&reg&,reg
1106 endif
1107 ENDM
1109 ; Macro to load an extended register with an integer value in either mode
1111 MACRO   loadint reg,val
1112 ifdef flatmodel
1113                 mov             e&reg&,val
1114 else
1115                 xor             e&reg&,e&reg&
1116                 mov     reg,val
1117 endif
1118 ENDM
1120 ; Macros to load and store integer values with string instructions
1122 MACRO   LODSINT
1123 ifdef flatmodel
1124                 lodsd
1125 else
1126                 lodsw
1127 endif
1128 ENDM
1130 MACRO   STOSINT
1131 ifdef flatmodel
1132                 stosd
1133 else
1134                 stosw
1135 endif
1136 ENDM
1138 ; Macros to provide resb, resw, resd compatibility with NASM
1140 MACRO   dclb    count
1141 db      count dup (0)
1142 ENDM
1144 MACRO   dclw    count
1145 dw      count dup (0)
1146 ENDM
1148 MACRO   dcld    count
1149 dd      count dup (0)
1150 ENDM
1152 ; Macros to provide resb, resw, resd compatibility with NASM
1154 MACRO   resb    count
1155 db      count dup (?)
1156 ENDM
1158 MACRO   resw    count
1159 dw      count dup (?)
1160 ENDM
1162 MACRO   resd    count
1163 dd      count dup (?)
1164 ENDM
1166 ; Macros to declare assembler stubs for function structures
1168 MACRO   BEGIN_STUBS_DEF name, firstOffset
1169 begdataseg  _STUBS
1170 ifdef   __NOU_VAR__
1171                 EXTRN   name:DWORD
1172 STUBS_START     =   name
1173 else
1174                 EXTRN   _&name&:DWORD
1175 name    EQU             _&name&
1176 STUBS_START     =   _&name
1177 endif
1178 enddataseg  _STUBS
1179 begcodeseg  _STUBS
1180 off = firstOffset
1181 ENDM
1183 MACRO   DECLARE_STUB    name
1184 ifdef   __NOU__
1185 name:
1186                 PUBLIC  name
1187 else
1188 _&name:
1189                 PUBLIC  _&name
1190 endif
1191                 jmp     [DWORD STUBS_START+off]
1192 off = off + 4
1193 ENDM
1195 MACRO   DECLARE_STDCALL name,num_args
1196 ifdef   STDCALL_MANGLE
1197 _&name&@&num_args&:
1198                 PUBLIC  _&name&@&num_args&
1199 else
1200 name:
1201                 PUBLIC  name
1202 endif
1203                 jmp     [DWORD STUBS_START+off]
1204 off = off + 4
1205 ENDM
1207 MACRO   END_STUBS_DEF
1208 endcodeseg  _STUBS
1209 ENDM
1211 MACRO   BEGIN_IMPORTS_DEF       name
1212 BEGIN_STUBS_DEF name,4
1213 ENDM
1215 MACRO   DECLARE_IMP     name
1216 DECLARE_STUB    name
1217 ENDM
1219 MACRO   END_IMPORTS_DEF
1220 END_STUBS_DEF
1221 ENDM
1223 endif