diff options
Diffstat (limited to 'misc')
-rw-r--r-- | misc/scitech.mac | 1223 |
1 files changed, 1223 insertions, 0 deletions
diff --git a/misc/scitech.mac b/misc/scitech.mac new file mode 100644 index 00000000..26f85f49 --- /dev/null +++ b/misc/scitech.mac @@ -0,0 +1,1223 @@ +;**************************************************************************** +;* +;* ======================================================================== +;* +;* The contents of this file are subject to the SciTech MGL Public +;* License Version 1.0 (the "License"); you may not use this file +;* except in compliance with the License. You may obtain a copy of +;* the License at http://www.scitechsoft.com/mgl-license.txt +;* +;* Software distributed under the License is distributed on an +;* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +;* implied. See the License for the specific language governing +;* rights and limitations under the License. +;* +;* The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc. +;* +;* The Initial Developer of the Original Code is SciTech Software, Inc. +;* All Rights Reserved. +;* +;* ======================================================================== +;* +;* Language: NetWide Assembler (NASM) or Turbo Assembler (TASM) +;* Environment: Any Intel Environment +;* +;* Description: Macros to provide memory model independant assembly language +;* module for C programming. Supports the large and flat memory +;* models. +;* +;* The defines that you should use when assembling modules that +;* use this macro package are: +;* +;* __LARGE__ Assemble for 16-bit large model +;* __FLAT__ Assemble for 32-bit FLAT memory model +;* __NOU__ No underscore for all external C labels +;* __NOU_VAR__ No underscore for global variables only +;* +;* The default settings are for 16-bit large memory model with +;* leading underscores for symbol names. +;* +;* The main intent of the macro file is to enable programmers +;* to write _one_ set of source that can be assembled to run +;* in either 16 bit real and protected modes or 32 bit +;* protected mode without the need to riddle the code with +;* 'if flatmodel' style conditional assembly (it is still there +;* but nicely hidden by a macro layer that enhances the +;* readability and understandability of the resulting code). +;* +;**************************************************************************** + +; Include the appropriate version in here depending on the assembler. NASM +; appears to always try and parse code, even if it is in a non-compiling +; block of a ifdef expression, and hence crashes if we include the TASM +; macro package in the same header file. Hence we split the macros up into +; two separate header files. + +ifdef __NASM_MAJOR__ + +;============================================================================ +; Macro package when compiling with NASM. +;============================================================================ + +; Turn off underscores for globals if disabled for all externals + +%ifdef __NOU__ +%define __NOU_VAR__ +%endif + +; Define the __WINDOWS__ symbol if we are compiling for any Windows +; environment + +%ifdef __WINDOWS16__ +%define __WINDOWS__ 1 +%endif +%ifdef __WINDOWS32__ +%define __WINDOWS__ 1 +%define __WINDOWS32_386__ 1 +%endif + +; Macros for accessing 'generic' registers + +%ifdef __FLAT__ +%idefine _ax eax +%idefine _bx ebx +%idefine _cx ecx +%idefine _dx edx +%idefine _si esi +%idefine _di edi +%idefine _bp ebp +%idefine _sp esp +%idefine _es +%idefine UCHAR BYTE ; Size of a character +%idefine USHORT WORD ; Size of a short +%idefine UINT DWORD ; Size of an integer +%idefine ULONG DWORD ; Size of a long +%idefine BOOL DWORD ; Size of a boolean +%idefine DPTR DWORD ; Size of a data pointer +%idefine FDPTR FWORD ; Size of a far data pointer +%idefine NDPTR DWORD ; Size of a near data pointer +%idefine CPTR DWORD ; Size of a code pointer +%idefine FCPTR FWORD ; Size of a far code pointer +%idefine NCPTR DWORD ; Size of a near code pointer +%idefine FPTR NEAR ; Distance for function pointers +%idefine DUINT dd ; Declare a integer variable +%idefine intsize 4 +%idefine flatmodel 1 +%else +%idefine _ax ax +%idefine _bx bx +%idefine _cx cx +%idefine _dx dx +%idefine _si si +%idefine _di di +%idefine _bp bp +%idefine _sp sp +%idefine _es es: +%idefine UCHAR BYTE ; Size of a character +%idefine USHORT WORD ; Size of a short +%idefine UINT WORD ; Size of an integer +%idefine ULONG DWORD ; Size of a long +%idefine BOOL WORD ; Size of a boolean +%idefine DPTR DWORD ; Size of a data pointer +%idefine FDPTR DWORD ; Size of a far data pointer +%idefine NDPTR WORD ; Size of a near data pointer +%idefine CPTR DWORD ; Size of a code pointer +%idefine FCPTR DWORD ; Size of a far code pointer +%idefine NCPTR WORD ; Size of a near code pointer +%idefine FPTR FAR ; Distance for function pointers +%idefine DUINT dw ; Declare a integer variable +%idefine intsize 2 +%endif +%idefine invert ~ +%idefine offset +%idefine use_nasm + +; Convert all jumps to near jumps, since NASM does not so this automatically + +%idefine jo jo near +%idefine jno jno near +%idefine jz jz near +%idefine jnz jnz near +%idefine je je near +%idefine jne jne near +%idefine jb jb near +%idefine jbe jbe near +%idefine ja ja near +%idefine jae jae near +%idefine jl jl near +%idefine jle jle near +%idefine jg jg near +%idefine jge jge near +%idefine jc jc near +%idefine jnc jnc near +%idefine js js near +%idefine jns jns near + +%ifdef DOUBLE +%idefine REAL QWORD +%idefine DREAL dq +%else +%idefine REAL DWORD +%idefine DREAL dd +%endif + +; Boolean truth values (same as those in debug.h) + +%idefine False 0 +%idefine True 1 +%idefine No 0 +%idefine Yes 1 +%idefine Yes 1 + +; Macro to be invoked at the start of all modules to set up segments for +; later use. Does nothing for NASM. + +%imacro header 1 +%endmacro + +; Macro to begin a data segment + +%imacro begdataseg 1 +%ifdef __GNUC__ +segment .data public class=DATA use32 flat +%else +%ifdef flatmodel +segment _DATA public align=4 class=DATA use32 flat +%else +segment _DATA public align=4 class=DATA use16 +%endif +%endif +%endmacro + +; Macro to end a data segment + +%imacro enddataseg 1 +%endmacro + +; Macro to begin a code segment + +%imacro begcodeseg 1 +%ifdef __GNUC__ +segment .text public class=CODE use32 flat +%else +%ifdef flatmodel +segment _TEXT public align=16 class=CODE use32 flat +%else +segment %1_TEXT public align=16 class=CODE use16 +%endif +%endif +%endmacro + +; Macro to begin a near code segment + +%imacro begcodeseg_near 0 +%ifdef __GNUC__ +segment .text public class=CODE use32 flat +%else +%ifdef flatmodel +segment _TEXT public align=16 class=CODE use32 flat +%else +segment _TEXT public align=16 class=CODE use16 +%endif +%endif +%endmacro + +; Macro to end a code segment + +%imacro endcodeseg 1 +%endmacro + +; Macro to end a near code segment + +%imacro endcodeseg_near 0 +%endmacro + +; Macro for an extern C symbol. If the C compiler requires leading +; underscores, then the underscores are added to the symbol names, otherwise +; they are left off. The symbol name is referenced in the assembler code +; using the non-underscored symbol name. + +%imacro cextern 2 +%ifdef __NOU_VAR__ +extern %1 +%else +extern _%1 +%define %1 _%1 +%endif +%endmacro + +%imacro cexternfunc 2 +%ifdef __NOU__ +extern %1 +%else +extern _%1 +%define %1 _%1 +%endif +%endmacro + +; Macro for a public C symbol. If the C compiler requires leading +; underscores, then the underscores are added to the symbol names, otherwise +; they are left off. The symbol name is referenced in the assembler code +; using the non-underscored symbol name. + +%imacro cpublic 1 +%ifdef __NOU_VAR__ +global %1 +%1: +%else +global _%1 +_%1: +%define %1 _%1 +%endif +%endmacro + +; Macro for an global C symbol. If the C compiler requires leading +; underscores, then the underscores are added to the symbol names, otherwise +; they are left off. The symbol name is referenced in the assembler code +; using the non-underscored symbol name. + +%imacro cglobal 1 +%ifdef __NOU_VAR__ +global %1 +%else +global _%1 +%define %1 _%1 +%endif +%endmacro + +; Macro for an global C function symbol. If the C compiler requires leading +; underscores, then the underscores are added to the symbol names, otherwise +; they are left off. The symbol name is referenced in the assembler code +; using the non-underscored symbol name. + +%imacro cglobalfunc 1 +%ifdef __NOU__ +global %1 +%else +global _%1 +%define %1 _%1 +%endif +%endmacro + +; Macro to start a C callable function. This will be a far function for +; 16-bit code, and a near function for 32-bit code. + +%imacro cprocstatic 1 +%push cproc +%1: +%ifdef flatmodel +%stacksize flat +%define ret retn +%else +%stacksize large +%define ret retf +%endif +%assign %$localsize 0 +%endmacro + +%imacro cprocstart 1 +%push cproc + cglobalfunc %1 +%1: +%ifdef flatmodel +%stacksize flat +%define ret retn +%else +%stacksize large +%define ret retf +%endif +%assign %$localsize 0 +%endmacro + +; This macro sets up a procedure to be exported from a 16 bit DLL. Since the +; calling conventions are always _far _pascal for 16 bit DLL's, we actually +; rename this routine with an extra underscore with 'C' calling conventions +; and a small DLL stub will be provided by the high level code to call the +; assembler routine. + +%imacro cprocstartdll16 1 +%ifdef __WINDOWS16__ +cprocstart _%1 +%else +cprocstart %1 +%endif +%endmacro + +; Macro to start a C callable near function. + +%imacro cprocnear 1 +%push cproc + cglobalfunc %1 +%1: +%define ret retn +%ifdef flatmodel +%stacksize flat +%else +%stacksize small +%endif +%assign %$localsize 0 +%endmacro + +; Macro to start a C callable far function. + +%imacro cprocfar 1 +%push cproc + cglobalfunc %1 +%1: +%define ret retf +%ifdef flatmodel +%stacksize flat +%else +%stacksize large +%endif +%assign %$localsize 0 +%endmacro + +; Macro to end a C function + +%imacro cprocend 0 +%pop +%endmacro + +; Macros for entering and exiting C callable functions. Note that we must +; always save and restore the SI and DI registers for C functions, and for +; 32 bit C functions we also need to save and restore EBX and clear the +; direction flag. + +%imacro enter_c 0 + push _bp + mov _bp,_sp +%ifnidn %$localsize,0 + sub _sp,%$localsize +%endif +%ifdef flatmodel + push ebx +%endif + push _si + push _di +%endmacro + +%imacro leave_c 0 + pop _di + pop _si +%ifdef flatmodel + pop ebx + cld +%endif +%ifnidn %$localsize,0 + mov _sp,_bp +%endif + pop _bp +%endmacro + +%imacro use_ebx 0 +%ifdef flatmodel + push ebx +%endif +%endmacro + +%imacro unuse_ebx 0 +%ifdef flatmodel + pop ebx +%endif +%endmacro + +; Macros for saving and restoring the value of DS,ES,FS,GS when it is to +; be used in assembly routines. This evaluates to nothing in the flat memory +; model, but is saves and restores DS in the large memory model. + +%imacro use_ds 0 +%ifndef flatmodel + push ds +%endif +%endmacro + +%imacro unuse_ds 0 +%ifndef flatmodel + pop ds +%endif +%endmacro + +%imacro use_es 0 +%ifndef flatmodel + push es +%endif +%endmacro + +%imacro unuse_es 0 +%ifndef flatmodel + pop es +%endif +%endmacro + +; Macros for loading the address of a data pointer into a segment and +; index register pair. The %imacro explicitly loads DS or ES in the 16 bit +; memory model, or it simply loads the offset into the register in the flat +; memory model since DS and ES always point to all addressable memory. You +; must use the correct _REG (ie: _BX) %imacros for documentation purposes. + +%imacro _lds 2 +%ifdef flatmodel + mov %1,%2 +%else + lds %1,%2 +%endif +%endmacro + +%imacro _les 2 +%ifdef flatmodel + mov %1,%2 +%else + les %1,%2 +%endif +%endmacro + +; Macros for adding and subtracting a value from registers. Two value are +; provided, one for 16 bit modes and another for 32 bit modes (the extended +; register is used in 32 bit modes). + +%imacro _add 3 +%ifdef flatmodel + add e%1, %3 +%else + add %1, %2 +%endif +%endmacro + +%imacro _sub 3 +%ifdef flatmodel + sub e%1, %3 +%else + sub %1, %2 +%endif +%endmacro + +; Macro to clear the high order word for the 32 bit extended registers. +; This is used to convert an unsigned 16 bit value to an unsigned 32 bit +; value, and will evaluate to nothing in 16 bit modes. + +%imacro clrhi 1 +%ifdef flatmodel + movzx e%1,%1 +%endif +%endmacro + +%imacro sgnhi 1 +%ifdef flatmodel + movsx e%1,%1 +%endif +%endmacro + +; Macro to load an extended register with an integer value in either mode + +%imacro loadint 2 +%ifdef flatmodel + mov e%1,%2 +%else + xor e%1,e%1 + mov %1,%2 +%endif +%endmacro + +; Macros to load and store integer values with string instructions + +%imacro LODSINT 0 +%ifdef flatmodel + lodsd +%else + lodsw +%endif +%endmacro + +%imacro STOSINT 0 +%ifdef flatmodel + stosd +%else + stosw +%endif +%endmacro + +; Macros to provide resb, resw, resd compatibility with NASM + +%imacro dclb 1 +times %1 db 0 +%endmacro + +%imacro dclw 1 +times %1 dw 0 +%endmacro + +%imacro dcld 1 +times %1 dd 0 +%endmacro + +; macros to declare assembler function stubs for function structures + +%imacro BEGIN_STUBS_DEF 2 +begdataseg _STUBS +%ifdef __NOU_VAR__ +extern %1 +%define STUBS_START %1 +%else +extern _%1 +%define STUBS_START _%1 +%endif +enddataseg _STUBS +begcodeseg _STUBS +%assign off %2 +%endmacro + +%imacro DECLARE_STUB 1 +%ifdef __NOU__ + global %1 +%1: +%else + global _%1 +_%1: +%endif + jmp [DWORD STUBS_START+off] +%assign off off+4 +%endmacro + +%imacro DECLARE_STDCALL 2 +%ifdef STDCALL_MANGLE + global _%1@%2 +_%1@%2: +%else +%ifdef __GNUC__ + global _%1 +_%1: +%else + global %1 +%1: +%endif +%endif + jmp [DWORD STUBS_START+off] +%assign off off+4 +%endmacro + +%imacro END_STUBS_DEF 0 +endcodeseg _STUBS +%endmacro + +; macros to declare assembler import stubs for binary loadable drivers + +%imacro BEGIN_IMPORTS_DEF 1 +BEGIN_STUBS_DEF %1,4 +%endmacro + +%imacro DECLARE_IMP 1 +DECLARE_STUB %1 +%endmacro + +%imacro END_IMPORTS_DEF 0 +END_STUBS_DEF +%endmacro + +else ; __NASM_MAJOR__ + +;============================================================================ +; Macro package when compiling with TASM. +;============================================================================ + +; Turn off underscores for globals if disabled for all externals + +ifdef __NOU__ +__NOU_VAR__ = 1 +endif + +; Define the __WINDOWS__ symbol if we are compiling for any Windows +; environment + +ifdef __WINDOWS16__ +__WINDOWS__ = 1 +endif +ifdef __WINDOWS32__ +__WINDOWS__ = 1 +__WINDOWS32_386__ = 1 +endif +ifdef __WIN386__ +__WINDOWS__ = 1 +__WINDOWS32_386__ = 1 +endif +ifdef __VXD__ +__WINDOWS__ = 1 +__WINDOWS32_386__ = 1 + MASM + .386 + NO_SEGMENTS = 1 + include vmm.inc ; IGNORE DEPEND + include vsegment.inc ; IGNORE DEPEND + IDEAL +endif + +; Macros for accessing 'generic' registers + +ifdef __FLAT__ + _ax EQU eax ; EAX is used for accumulator + _bx EQU ebx ; EBX is used for accumulator + _cx EQU ecx ; ECX is used for looping + _dx EQU edx ; EDX is used for data register + _si EQU esi ; ESI is the source index register + _di EQU edi ; EDI is the destination index register + _bp EQU ebp ; EBP is used for base pointer register + _sp EQU esp ; ESP is used for stack pointer register + _es EQU ; ES and DS are the same in 32 bit PM + typedef UCHAR BYTE ; Size of a character + typedef USHORT WORD ; Size of a short + typedef UINT DWORD ; Size of an integer + typedef ULONG DWORD ; Size of a long + typedef BOOL DWORD ; Size of a boolean + typedef DPTR DWORD ; Size of a data pointer + typedef FDPTR FWORD ; Size of a far data pointer + typedef NDPTR DWORD ; Size of a near data pointer + typedef CPTR DWORD ; Size of a code pointer + typedef FCPTR FWORD ; Size of a far code pointer + typedef NCPTR DWORD ; Size of a near code pointer + typedef DUINT DWORD ; Declare a integer variable + FPTR EQU NEAR ; Distance for function pointers + intsize = 4 ; Size of an integer + flatmodel = 1 ; This is a flat memory model + P386 ; Turn on 386 code generation + MODEL FLAT ; Set up for 32 bit simplified FLAT model +else + _ax EQU ax ; AX is used for accumulator + _bx EQU bx ; BX is used for accumulator + _cx EQU cx ; CX is used for looping + _dx EQU dx ; DX is used for data register + _si EQU si ; SI is the source index register + _di EQU di ; DI is the destination index register + _bp EQU bp ; BP is used for base pointer register + _sp EQU sp ; SP is used for stack pointer register + _es EQU es: ; ES is used for segment override + typedef UCHAR BYTE ; Size of a character + typedef USHORT WORD ; Size of a short + typedef UINT WORD ; Size of an integer + typedef ULONG DWORD ; Size of a long + typedef BOOL WORD ; Size of a boolean + typedef DPTR DWORD ; Size of a data pointer + typedef FDPTR DWORD ; Size of a far data pointer + typedef NDPTR WORD ; Size of a near data pointer + typedef CPTR DWORD ; Size of a code pointer + typedef FCPTR DWORD ; Size of a far code pointer + typedef NCPTR WORD ; Size of a near code pointer + typedef DUINT WORD ; Declare a integer variable + FPTR EQU FAR ; Distance for function pointers + intsize = 2 ; Size of an integer + P386 ; Turn on 386 code generation +endif + invert EQU not + +; Provide a typedef for real floating point numbers + +ifdef DOUBLE +typedef REAL QWORD +typedef DREAL QWORD +else +typedef REAL DWORD +typedef DREAL DWORD +endif + +; Macros to access the floating point stack registers to convert them +; from NASM style to TASM style + +st0 EQU st(0) +st1 EQU st(1) +st2 EQU st(2) +st3 EQU st(3) +st4 EQU st(4) +st5 EQU st(5) +st6 EQU st(6) +st7 EQU st(7) +st8 EQU st(8) + +; Boolean truth values (same as those in debug.h) + +ifndef __VXD__ +False = 0 +True = 1 +No = 0 +Yes = 1 +Yes = 1 +endif + +; Macros for the _DATA data segment. This segment contains initialised data. + +MACRO begdataseg name +ifdef __VXD__ + MASM +VXD_LOCKED_DATA_SEG + IDEAL +else +ifdef flatmodel + DATASEG +else +SEGMENT _DATA DWORD PUBLIC USE16 'DATA' +endif +endif +ENDM + +MACRO enddataseg name +ifdef __VXD__ + MASM +VXD_LOCKED_DATA_ENDS + IDEAL +else +ifndef flatmodel +ENDS _DATA +endif +endif +ENDM + +; Macro for the main code segment. + +MACRO begcodeseg name +ifdef __VXD__ + MASM +VXD_LOCKED_CODE_SEG + IDEAL +else +ifdef flatmodel + CODESEG + ASSUME CS:FLAT,DS:FLAT,SS:FLAT +else +SEGMENT &name&_TEXT PARA PUBLIC USE16 'CODE' + ASSUME CS:&name&_TEXT,DS:_DATA +endif +endif +ENDM + +; Macro for a near code segment + +MACRO begcodeseg_near +ifdef flatmodel + CODESEG + ASSUME CS:FLAT,DS:FLAT,SS:FLAT +else +SEGMENT _TEXT PARA PUBLIC USE16 'CODE' + ASSUME CS:_TEXT,DS:_DATA +endif +ENDM + +MACRO endcodeseg name +ifdef __VXD__ + MASM +VXD_LOCKED_CODE_ENDS + IDEAL +else +ifndef flatmodel +ENDS &name&_TEXT +endif +endif +ENDM + +MACRO endcodeseg_near +ifndef flatmodel +ENDS _TEXT +endif +ENDM + +; Macro to be invoked at the start of all modules to set up segments for +; later use. + +MACRO header name +begdataseg name +enddataseg name +ENDM + +; Macro for an extern C symbol. If the C compiler requires leading +; underscores, then the underscores are added to the symbol names, otherwise +; they are left off. The symbol name is referenced in the assembler code +; using the non-underscored symbol name. + +MACRO cextern name,size +ifdef __NOU_VAR__ + EXTRN name:size +else + EXTRN _&name&:size +name EQU _&name& +endif +ENDM + +MACRO cexternfunc name,size +ifdef __NOU__ + EXTRN name:size +else + EXTRN _&name&:size +name EQU _&name& +endif +ENDM + +MACRO stdexternfunc name,args,size +ifdef STDCALL_MANGLE + EXTRN _&name&@&num_args&:size +name EQU _&name&@&num_args +else + EXTRN name:size +endif +ENDM + +; Macro for a public C symbol. If the C compiler requires leading +; underscores, then the underscores are added to the symbol names, otherwise +; they are left off. The symbol name is referenced in the assembler code +; using the non-underscored symbol name. + +MACRO cpublic name +ifdef __NOU_VAR__ +name: + PUBLIC name +else +_&name&: + PUBLIC _&name& +name EQU _&name& +endif +ENDM + +; Macro for an global C symbol. If the C compiler requires leading +; underscores, then the underscores are added to the symbol names, otherwise +; they are left off. The symbol name is referenced in the assembler code +; using the non-underscored symbol name. + +MACRO cglobal name +ifdef __NOU_VAR__ + PUBLIC name +else + PUBLIC _&name& +name EQU _&name& +endif +ENDM + +; Macro for an global C function symbol. If the C compiler requires leading +; underscores, then the underscores are added to the symbol names, otherwise +; they are left off. The symbol name is referenced in the assembler code +; using the non-underscored symbol name. + +MACRO cglobalfunc name +ifdef __NOU__ + PUBLIC name +else + PUBLIC _&name& +name EQU _&name& +endif +ENDM + +; Macro to start a C callable function. This will be a far function for +; 16-bit code, and a near function for 32-bit code. + +MACRO cprocstatic name ; Set up model independant private proc +ifdef flatmodel +PROC name NEAR +else +PROC name FAR +endif +LocalSize = 0 +ENDM + +MACRO cprocstart name ; Set up model independant proc +ifdef flatmodel +ifdef __NOU__ +PROC name NEAR +else +PROC _&name& NEAR +endif +else +ifdef __NOU__ +PROC name FAR +else +PROC _&name& FAR +endif +endif +LocalSize = 0 + cglobalfunc name +ENDM + +MACRO cprocnear name ; Set up near proc +ifdef __NOU__ +PROC name NEAR +else +PROC _&name& NEAR +endif +LocalSize = 0 + cglobalfunc name +ENDM + +MACRO cprocfar name ; Set up far proc +ifdef __NOU__ +PROC name FAR +else +PROC _&name& FAR +endif +LocalSize = 0 + cglobalfunc name +ENDM + +MACRO cprocend ; End procedure macro +ENDP +ENDM + +; This macro sets up a procedure to be exported from a 16 bit DLL. Since the +; calling conventions are always _far _pascal for 16 bit DLL's, we actually +; rename this routine with an extra underscore with 'C' calling conventions +; and a small DLL stub will be provided by the high level code to call the +; assembler routine. + +MACRO cprocstartdll16 name +ifdef __WINDOWS16__ +cprocstart _&name& +else +cprocstart name +endif +ENDM + +; Macros for entering and exiting C callable functions. Note that we must +; always save and restore the SI and DI registers for C functions, and for +; 32 bit C functions we also need to save and restore EBX and clear the +; direction flag. + +MACRO save_c_regs +ifdef flatmodel + push ebx +endif + push _si + push _di +ENDM + +MACRO enter_c + push _bp + mov _bp,_sp + IFDIFI <LocalSize>,<0> + sub _sp,LocalSize + ENDIF + save_c_regs +ENDM + +MACRO restore_c_regs + pop _di + pop _si +ifdef flatmodel + pop ebx +endif +ENDM + +MACRO leave_c + restore_c_regs + cld + IFDIFI <LocalSize>,<0> + mov _sp,_bp + ENDIF + pop _bp +ENDM + +MACRO use_ebx +ifdef flatmodel + push ebx +endif +ENDM + +MACRO unuse_ebx +ifdef flatmodel + pop ebx +endif +ENDM + +; Macros for saving and restoring the value of DS,ES,FS,GS when it is to +; be used in assembly routines. This evaluates to nothing in the flat memory +; model, but is saves and restores DS in the large memory model. + +MACRO use_ds +ifndef flatmodel + push ds +endif +ENDM + +MACRO unuse_ds +ifndef flatmodel + pop ds +endif +ENDM + +MACRO use_es +ifndef flatmodel + push es +endif +ENDM + +MACRO unuse_es +ifndef flatmodel + pop es +endif +ENDM + +; Macros for loading the address of a data pointer into a segment and +; index register pair. The macro explicitly loads DS or ES in the 16 bit +; memory model, or it simply loads the offset into the register in the flat +; memory model since DS and ES always point to all addressable memory. You +; must use the correct _REG (ie: _BX) macros for documentation purposes. + +MACRO _lds reg, addr +ifdef flatmodel + mov reg,addr +else + lds reg,addr +endif +ENDM + +MACRO _les reg, addr +ifdef flatmodel + mov reg,addr +else + les reg,addr +endif +ENDM + +; Macros for adding and subtracting a value from registers. Two value are +; provided, one for 16 bit modes and another for 32 bit modes (the extended +; register is used in 32 bit modes). + +MACRO _add reg, val16, val32 +ifdef flatmodel + add e®&, val32 +else + add reg, val16 +endif +ENDM + +MACRO _sub reg, val16, val32 +ifdef flatmodel + sub e®&, val32 +else + sub reg, val16 +endif +ENDM + +; Macro to clear the high order word for the 32 bit extended registers. +; This is used to convert an unsigned 16 bit value to an unsigned 32 bit +; value, and will evaluate to nothing in 16 bit modes. + +MACRO clrhi reg +ifdef flatmodel + movzx e®&,reg +endif +ENDM + +MACRO sgnhi reg +ifdef flatmodel + movsx e®&,reg +endif +ENDM + +; Macro to load an extended register with an integer value in either mode + +MACRO loadint reg,val +ifdef flatmodel + mov e®&,val +else + xor e®&,e®& + mov reg,val +endif +ENDM + +; Macros to load and store integer values with string instructions + +MACRO LODSINT +ifdef flatmodel + lodsd +else + lodsw +endif +ENDM + +MACRO STOSINT +ifdef flatmodel + stosd +else + stosw +endif +ENDM + +; Macros to provide resb, resw, resd compatibility with NASM + +MACRO dclb count +db count dup (0) +ENDM + +MACRO dclw count +dw count dup (0) +ENDM + +MACRO dcld count +dd count dup (0) +ENDM + +; Macros to provide resb, resw, resd compatibility with NASM + +MACRO resb count +db count dup (?) +ENDM + +MACRO resw count +dw count dup (?) +ENDM + +MACRO resd count +dd count dup (?) +ENDM + +; Macros to declare assembler stubs for function structures + +MACRO BEGIN_STUBS_DEF name, firstOffset +begdataseg _STUBS +ifdef __NOU_VAR__ + EXTRN name:DWORD +STUBS_START = name +else + EXTRN _&name&:DWORD +name EQU _&name& +STUBS_START = _&name +endif +enddataseg _STUBS +begcodeseg _STUBS +off = firstOffset +ENDM + +MACRO DECLARE_STUB name +ifdef __NOU__ +name: + PUBLIC name +else +_&name: + PUBLIC _&name +endif + jmp [DWORD STUBS_START+off] +off = off + 4 +ENDM + +MACRO DECLARE_STDCALL name,num_args +ifdef STDCALL_MANGLE +_&name&@&num_args&: + PUBLIC _&name&@&num_args& +else +name: + PUBLIC name +endif + jmp [DWORD STUBS_START+off] +off = off + 4 +ENDM + +MACRO END_STUBS_DEF +endcodeseg _STUBS +ENDM + +MACRO BEGIN_IMPORTS_DEF name +BEGIN_STUBS_DEF name,4 +ENDM + +MACRO DECLARE_IMP name +DECLARE_STUB name +ENDM + +MACRO END_IMPORTS_DEF +END_STUBS_DEF +ENDM + +endif |