mirror of
				https://github.com/netwide-assembler/nasm.git
				synced 2025-10-10 00:25:06 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			1224 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			1224 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| ;****************************************************************************
 | |
| ;*
 | |
| ;*  ========================================================================
 | |
| ;*
 | |
| ;*    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
 |