| ;**************************************************************************** |
| ;* |
| ;* ======================================================================== |
| ;* |
| ;* 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 __PIC__ |
| %ifdef __LINUX__ |
| extern _GLOBAL_OFFSET_TABLE_ |
| %else |
| extern __GLOBAL_OFFSET_TABLE_ |
| %endif |
| %endif |
| %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 __PIC__ |
| global %1:function |
| %else |
| %ifdef __NOU__ |
| global %1 |
| %else |
| global _%1 |
| %define %1 _%1 |
| %endif |
| %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 |
| |
| ; Macro to get the addres of the GOT for Linux/FreeBSD shared |
| ; libraries into the EBX register. |
| |
| %imacro get_GOT 1 |
| call %%getgot |
| %%getgot: pop %1 |
| add %1,_GLOBAL_OFFSET_TABLE_+$$-%%getgot wrt ..gotpc |
| %endmacro |
| |
| ; Macro to get the address of a *local* variable that is global to |
| ; a single module in a manner that will work correctly when compiled |
| ; into a Linux shared library. Note that this will *not* work for |
| ; variables that are defined as global to all modules. For that |
| ; use the LEA_G macro |
| |
| %macro LEA_L 2 |
| %ifdef __PIC__ |
| get_GOT %1 |
| lea %1,[%1+%2 wrt ..gotoff] |
| %else |
| lea %1,[%2] |
| %endif |
| %endmacro |
| |
| ; Same macro as above but for global variables public to *all* |
| ; modules. |
| |
| %macro LEA_G 2 |
| %ifdef __PIC__ |
| get_GOT %1 |
| mov %1,[%1+%2 wrt ..got] |
| %else |
| lea %1,[%2] |
| %endif |
| %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 __PIC__ |
| global %1:function |
| %1: |
| get_GOT eax |
| mov eax,[eax+STUBS_START wrt ..got] |
| jmp [eax+off] |
| %else |
| %ifdef __NOU__ |
| global %1 |
| %1: |
| %else |
| global _%1 |
| _%1: |
| %endif |
| jmp [DWORD STUBS_START+off] |
| %endif |
| %assign off off+4 |
| %endmacro |
| |
| %imacro SKIP_STUB 1 |
| %assign off off+4 |
| %endmacro |
| |
| %imacro DECLARE_STDCALL 2 |
| %ifdef STDCALL_MANGLE |
| global _%1@%2 |
| _%1@%2: |
| %else |
| %ifdef STDCALL_USCORE |
| 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 2 |
| DECLARE_STUB %1 |
| %endmacro |
| |
| %imacro SKIP_IMP 2 |
| SKIP_STUB %1 |
| %endmacro |
| |
| %imacro SKIP_IMP2 1 |
| DECLARE_STUB %1 |
| %endmacro |
| |
| %imacro SKIP_IMP3 1 |
| SKIP_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,num_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 SKIP_STUB name |
| 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 |
| |
| ifndef LOCAL_DECLARE_IMP |
| MACRO DECLARE_IMP name, numArgs |
| DECLARE_STUB name |
| ENDM |
| |
| MACRO SKIP_IMP name |
| SKIP_STUB name |
| ENDM |
| |
| MACRO SKIP_IMP2 name, numArgs |
| DECLARE_STUB name |
| ENDM |
| |
| MACRO SKIP_IMP3 name |
| SKIP_STUB name |
| ENDM |
| endif |
| |
| MACRO END_IMPORTS_DEF |
| END_STUBS_DEF |
| ENDM |
| |
| MACRO LEA_L reg,name |
| lea reg,[name] |
| ENDM |
| |
| MACRO LEA_G reg,name |
| lea reg,[name] |
| ENDM |
| |
| endif |
| |