1304 lines
21 KiB
NASM
1304 lines
21 KiB
NASM
;_ macros.asm
|
||
; Copyright (C) 1985-1991 by Walter Bright
|
||
; All Rights Reserved
|
||
; Modified for COFF and ELF support by David Bustin
|
||
; $Revision: 1.1.1.1 $
|
||
|
||
ifdef _WIN32
|
||
ifndef __NT__
|
||
__NT__ equ 1
|
||
endif
|
||
endif
|
||
|
||
ifndef M_I386
|
||
|
||
ifdef _WINDOWS
|
||
extrn MESSAGEFATALERROR : far
|
||
endif
|
||
|
||
; modified for RATIONAL support by P Murray, April 1990
|
||
; define DOS16RM for protected mode programs
|
||
|
||
; Determine which memory model we are assembling for. For .COM files,
|
||
; force S model.
|
||
|
||
ifdef DOS16RM
|
||
ifndef I8086L
|
||
%out Only L model supported with RATIONAL DOS Extender.
|
||
end
|
||
endif
|
||
else
|
||
ifdef I8086T
|
||
I8086S equ 1
|
||
else
|
||
ifndef I8086S
|
||
ifndef I8086M
|
||
ifndef I8086C
|
||
ifndef I8086L ;if none of the memory models are defined
|
||
ifndef I8086V
|
||
I8086S equ 1 ;default to S model
|
||
endif ;I8086V
|
||
endif ;I8086L
|
||
endif ;I8086C
|
||
endif ;I8086M
|
||
endif ;I8086S
|
||
endif ;I8086T
|
||
endif ;DOS16RM
|
||
|
||
ifdef __OS2__
|
||
.286C
|
||
endif
|
||
|
||
|
||
ifdef DOS16RM
|
||
.286P
|
||
endif
|
||
|
||
ifndef I386
|
||
I386 equ 0
|
||
endif
|
||
|
||
;Decide if SI and DI are saved across function calls
|
||
SAVESIDI equ 1 ;1 means SI and DI are saved across functions
|
||
|
||
if 0 ;Lattice conventions no longer supported
|
||
MSC equ 1 ;ifdef means use Microsoft C calling conventions
|
||
;ifndef means use Lattice
|
||
endif
|
||
|
||
; Macros to bracket data segment stuff.
|
||
|
||
ifndef STARTUP
|
||
begdata macro
|
||
|
||
ifdef DOS16RM
|
||
;Segment so we can find the start of DGROUP
|
||
|
||
NULL segment para public 'BEGDATA' ;Note PARAGRAPH alignment
|
||
NULL ends
|
||
endif
|
||
|
||
_DATA segment word public 'DATA'
|
||
_DATA ends
|
||
CONST segment word public 'CONST'
|
||
CONST ends
|
||
_BSS segment word public 'BSS'
|
||
_BSS ends
|
||
ifdef DOS16RM
|
||
DGROUP group NULL,_DATA,CONST,_BSS
|
||
else
|
||
DGROUP group _DATA,CONST,_BSS
|
||
endif
|
||
_DATA segment
|
||
assume ds:DGROUP
|
||
endm
|
||
endif ; STARTUP
|
||
|
||
enddata macro
|
||
_DATA ends
|
||
endm
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
; Macros specific to each memory model in an attempt to make it easier
|
||
; to write memory model independent code.
|
||
; begcode,endcode Use to bracket code sections
|
||
; P Offset on BP to first argument on stack
|
||
; (excluding any local variables)
|
||
; SPTR 1 if small data model
|
||
; LPTR 1 if large pointers (large data)
|
||
; LCODE 1 if large code model
|
||
; ESeqDS 1 if ES == DS at all times
|
||
; SSeqDS 1 if SS == DS at all times
|
||
; SIZEPTR # of bytes in a pointer
|
||
; func Declare a function as NEAR or FAR
|
||
; callm Call function as NEAR or FAR
|
||
|
||
;;;;;;;;;;;;;; SMALL MEMORY MODEL ;;;;;;;;;;;;;;;;;
|
||
ifdef I8086S
|
||
begcode macro module
|
||
_TEXT segment word public 'CODE'
|
||
assume cs:_TEXT
|
||
endm
|
||
|
||
endcode macro module
|
||
_TEXT ENDS
|
||
endm
|
||
|
||
P equ 4 ; Offset of start of parameters on the stack frame
|
||
SPTR equ 1
|
||
LPTR equ 0
|
||
LCODE equ 0
|
||
ESeqDS equ 0
|
||
SSeqDS equ 1
|
||
SIZEPTR equ 2 ; Size of a pointer
|
||
|
||
p_func macro name
|
||
name proc near
|
||
endm
|
||
|
||
p_endp macro name
|
||
name endp
|
||
endm
|
||
|
||
callp macro name
|
||
call near ptr name
|
||
endm
|
||
|
||
func macro name
|
||
_&name proc near
|
||
ifndef name
|
||
name equ _&name
|
||
endif
|
||
endm
|
||
|
||
callm macro name
|
||
call near ptr _&name
|
||
endm
|
||
endif
|
||
|
||
;;;;;;;;;;;;;;;;; MEDIUM MEMORY MODEL ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
||
ifdef I8086M
|
||
begcode macro module
|
||
module&_TEXT segment para public 'CODE'
|
||
assume cs:module&_TEXT
|
||
endm
|
||
|
||
endcode macro module
|
||
module&_TEXT ends
|
||
endm
|
||
|
||
P equ 6 ; Offset of start of parameters on the stack frame
|
||
SPTR equ 1
|
||
LPTR equ 0
|
||
LCODE equ 1
|
||
ESeqDS equ 0
|
||
SSeqDS equ 1
|
||
SIZEPTR equ 2
|
||
|
||
p_func macro name
|
||
name proc far
|
||
endm
|
||
|
||
p_endp macro name
|
||
name endp
|
||
endm
|
||
|
||
callp macro name
|
||
call far ptr name
|
||
endm
|
||
|
||
func macro name
|
||
_&name proc far
|
||
ifndef name
|
||
name equ _&name
|
||
endif
|
||
endm
|
||
|
||
callm macro name
|
||
call far ptr _&name
|
||
endm
|
||
endif
|
||
|
||
;;;;;;;;;;;;;;;;; COMPACT MEMORY MODEL ;;;;;;;;;;;;;;
|
||
|
||
ifdef I8086C
|
||
begcode macro module
|
||
_TEXT segment word public 'CODE'
|
||
assume cs:_TEXT
|
||
endm
|
||
|
||
endcode macro module
|
||
_TEXT ends
|
||
endm
|
||
|
||
P equ 4 ; Offset of start of parameters on the stack frame
|
||
SPTR equ 0
|
||
LPTR equ 1
|
||
LCODE equ 0
|
||
ESeqDS equ 0
|
||
SSeqDS equ 0
|
||
SIZEPTR equ 4
|
||
|
||
p_func macro name
|
||
name proc near
|
||
endm
|
||
|
||
p_endp macro name
|
||
name endp
|
||
endm
|
||
|
||
callp macro name
|
||
call near ptr name
|
||
endm
|
||
|
||
func macro name
|
||
_&name proc near
|
||
ifndef name
|
||
name equ _&name
|
||
endif
|
||
endm
|
||
|
||
callm macro name
|
||
call near ptr _&name
|
||
endm
|
||
endif
|
||
|
||
;;;;;;;;;;;;;;;; LARGE MEMORY MODEL ;;;;;;;;;;;;;;;;;;;
|
||
|
||
ifdef I8086L
|
||
begcode macro module
|
||
module&_TEXT segment para public 'CODE'
|
||
assume cs:module&_TEXT
|
||
endm
|
||
|
||
endcode macro module
|
||
module&_TEXT ends
|
||
endm
|
||
|
||
P equ 6 ; Offset of start of parameters on the stack frame
|
||
SPTR equ 0
|
||
LPTR equ 1
|
||
LCODE equ 1
|
||
ESeqDS equ 0
|
||
SSeqDS equ 0
|
||
SIZEPTR equ 4
|
||
|
||
p_func macro name
|
||
name proc far
|
||
endm
|
||
|
||
p_endp macro name
|
||
name endp
|
||
endm
|
||
|
||
callp macro name
|
||
call far ptr name
|
||
endm
|
||
|
||
func macro name
|
||
_&name proc far
|
||
ifndef name
|
||
name equ _&name
|
||
endif
|
||
endm
|
||
|
||
callm macro name
|
||
call far ptr _&name
|
||
endm
|
||
endif
|
||
|
||
;Macros to replace public, extrn, and endp for C-callable assembly routines,
|
||
; and to define labels: c_label defines labels,
|
||
; c_public replaces public, c_extrn replaces extrn, and c_endp replaces endp
|
||
|
||
c_name macro name
|
||
name equ _&name
|
||
endm
|
||
|
||
c_label macro name
|
||
_&name:
|
||
endm
|
||
|
||
c_public macro a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
|
||
ifnb <a> ;;Check for blank argument
|
||
public _&a
|
||
a equ _&a
|
||
ifnb <b>
|
||
c_public b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
|
||
endif
|
||
endif
|
||
endm
|
||
|
||
c_extrn macro a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
|
||
ifnb <a> ;;Check for blank argument
|
||
extrn _&a:b
|
||
a equ _&a
|
||
ifnb <c>
|
||
c_extrn c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
|
||
endif
|
||
endif
|
||
endm
|
||
|
||
c_endp macro name
|
||
_&name ENDP
|
||
endm
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
; Define function ctor as a static constructor
|
||
static_ctor macro ctor
|
||
if LCODE
|
||
XIFB segment word public 'DATA'
|
||
XIFB ends
|
||
XIF segment word public 'DATA'
|
||
dd ctor
|
||
XIF ends
|
||
XIFE segment word public 'DATA'
|
||
XIFE ends
|
||
else
|
||
XIB segment word public 'DATA'
|
||
XIB ends
|
||
XI segment word public 'DATA'
|
||
dw ctor
|
||
XI ends
|
||
XIE segment word public 'DATA'
|
||
XIE ends
|
||
endif
|
||
endm
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
; Define function ctor as a static destructor
|
||
static_dtor macro dtor
|
||
if LCODE
|
||
XCFB segment word public 'DATA'
|
||
XCFB ends
|
||
XCF segment word public 'DATA'
|
||
dd dtor
|
||
XCF ends
|
||
XCFE segment word public 'DATA'
|
||
XCFE ends
|
||
else
|
||
XCB segment word public 'DATA'
|
||
XCB ends
|
||
XC segment word public 'DATA'
|
||
dw dtor
|
||
XC ends
|
||
XCE segment word public 'DATA'
|
||
XCE ends
|
||
endif
|
||
endm
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
; Other more or less useful macros
|
||
; Commented out ones are obsolete
|
||
|
||
;setESeqDS macro ;set ES == DS, if not already true
|
||
; ife ESeqDS
|
||
; push DS
|
||
; pop ES
|
||
; endif
|
||
; endm
|
||
|
||
.push macro list
|
||
irp arg,<list>
|
||
push arg
|
||
endm
|
||
endm
|
||
|
||
.pop macro list
|
||
irp arg,<list>
|
||
pop arg
|
||
endm
|
||
endm
|
||
|
||
_push macro list
|
||
irp arg,<list>
|
||
push arg
|
||
endm
|
||
endm
|
||
|
||
_pop macro list
|
||
irp arg,<list>
|
||
pop arg
|
||
endm
|
||
endm
|
||
|
||
; Macros to save and restore regs destroyed by a function
|
||
|
||
.save macro list
|
||
if SAVESIDI
|
||
irp arg,<list>
|
||
push arg
|
||
endm
|
||
endif
|
||
endm
|
||
|
||
.restore macro list
|
||
if SAVESIDI
|
||
irp arg,<list>
|
||
pop arg
|
||
endm
|
||
endif
|
||
endm
|
||
|
||
_save macro list
|
||
if SAVESIDI
|
||
irp arg,<list>
|
||
push arg
|
||
endm
|
||
endif
|
||
endm
|
||
|
||
_restore macro list
|
||
if SAVESIDI
|
||
irp arg,<list>
|
||
pop arg
|
||
endm
|
||
endif
|
||
endm
|
||
|
||
; Macros to save and restore ES, but only if ESeqDS is 1.
|
||
;pushES macro
|
||
; if ESeqDS
|
||
; push ES
|
||
; endif
|
||
; endm
|
||
;
|
||
;popES macro
|
||
; if ESeqDS
|
||
; pop ES
|
||
; endif
|
||
; endm
|
||
|
||
clr macro list ;clear a register
|
||
irp reg,<list>
|
||
xor reg,reg
|
||
endm
|
||
endm
|
||
|
||
tst macro reg
|
||
test reg,reg
|
||
endm
|
||
|
||
jmps macro lbl
|
||
jmp short lbl
|
||
endm
|
||
|
||
if @Version lt 600
|
||
;For compatibility with MASM 5.10
|
||
.if macro arg1,cond,arg2,lbl
|
||
cmp arg1,arg2
|
||
j&cond lbl
|
||
endm
|
||
|
||
endif
|
||
|
||
_if macro arg1,cond,arg2,lbl
|
||
cmp arg1,arg2
|
||
j&cond lbl
|
||
endm
|
||
|
||
;sob macro arg,lbl
|
||
; ifidn <arg>,<CX>
|
||
; loop lbl
|
||
; else
|
||
; dec arg
|
||
; jnz lbl
|
||
; endif
|
||
; endm
|
||
|
||
|
||
ifdef _WINDOWS
|
||
extrn DOS3CALL : far
|
||
endif
|
||
|
||
ifndef nobdos
|
||
bdos macro func
|
||
ifnb <func>
|
||
mov AH,func
|
||
endif
|
||
ifndef _WINDOWS
|
||
int 21h
|
||
else
|
||
call DOS3CALL
|
||
endif
|
||
endm
|
||
|
||
dpmi macro func
|
||
ifnb <func>
|
||
mov AX,func
|
||
endif
|
||
int 31h
|
||
endm
|
||
else
|
||
__bdos macro func
|
||
ifnb <func>
|
||
mov AH,func
|
||
endif
|
||
ifndef _WINDOWS
|
||
int 21h
|
||
else
|
||
call DOS3CALL
|
||
endif
|
||
endm
|
||
|
||
__dpmi macro func
|
||
ifnb <func>
|
||
mov AX,func
|
||
endif
|
||
int 31h
|
||
endm
|
||
endif
|
||
|
||
.retf macro val ;force assembler to build a far return
|
||
ifnb <val>
|
||
db 0CAh
|
||
dw val
|
||
else
|
||
db 0CBh
|
||
endif
|
||
endm
|
||
|
||
_retf macro val ;force assembler to build a far return
|
||
ifnb <val>
|
||
db 0CAh
|
||
dw val
|
||
else
|
||
db 0CBh
|
||
endif
|
||
endm
|
||
|
||
; Sometimes MASM ignores my segment overrides.
|
||
segES macro
|
||
db 26h
|
||
endm
|
||
|
||
; 32 bit negate
|
||
neg32 macro reg1,reg2
|
||
neg reg1
|
||
neg reg2
|
||
sbb reg1,0
|
||
endm
|
||
|
||
; Push immediate (reg is for scratch)
|
||
pushi macro reg,value
|
||
if 0
|
||
push value ;for 286 code generation only
|
||
else
|
||
mov reg,value
|
||
push reg
|
||
endif
|
||
endm
|
||
|
||
; Inc/dec BP if I8086V memory model
|
||
incBP macro
|
||
ifdef I8086V
|
||
inc BP
|
||
endif
|
||
endm
|
||
|
||
decBP macro
|
||
ifdef I8086V
|
||
dec BP
|
||
endif
|
||
endm
|
||
|
||
WINENTER macro
|
||
ifdef _WINDOWS
|
||
ifndef I8086S
|
||
ifndef I8086C
|
||
inc BP
|
||
endif
|
||
endif
|
||
endif
|
||
push BP
|
||
mov BP,SP
|
||
endm
|
||
|
||
WINLEAVE macro
|
||
pop BP
|
||
ifdef _WINDOWS
|
||
ifndef I8086S
|
||
ifndef I8086C
|
||
dec BP
|
||
endif
|
||
endif
|
||
endif
|
||
endm
|
||
|
||
WINENTER_NF macro
|
||
ifdef _WINDOWS
|
||
ifndef I8086S
|
||
ifndef I8086C
|
||
inc BP
|
||
push BP
|
||
mov BP,SP
|
||
endif
|
||
endif
|
||
endif
|
||
endm
|
||
|
||
WINLEAVE_NF macro
|
||
ifdef _WINDOWS
|
||
ifndef I8086S
|
||
ifndef I8086C
|
||
pop BP
|
||
dec BP
|
||
endif
|
||
endif
|
||
endif
|
||
endm
|
||
|
||
else ;M_I386
|
||
|
||
.386P
|
||
.387
|
||
|
||
ifdef DOS386
|
||
SEG_1ST_MEG equ 034h ;Selector of 1st Mbyte used by MSDOS
|
||
SEG_SCREEN equ 01ch ;Selector for the video memory.
|
||
SEG_PSP equ 024H ;PSP selector.
|
||
SEG_DGROUP equ 014H ;DGROUP selector.
|
||
SEG_ENV equ 02cH ;Selector of environment string.
|
||
|
||
OMF equ 1
|
||
COFF equ 0
|
||
ELF equ 0
|
||
_FLAT equ 0 ;FLAT memory model
|
||
_STDCALL equ 0 ;default to _stdcall
|
||
_RETST0 equ 0 ;return floating point results in ST0
|
||
endif ;DOS386
|
||
|
||
ifdef X386
|
||
_FLAT equ 0
|
||
_STDCALL equ 0
|
||
_RETST0 equ 0
|
||
endif
|
||
|
||
ifdef __OS2__
|
||
OMF equ 1
|
||
COFF equ 0
|
||
ELF equ 0
|
||
_FLAT equ 1 ;FLAT memory model
|
||
_STDCALL equ 1
|
||
_RETST0 equ 1
|
||
_INLINE_8087 equ 1 ;defined if we always generate inline 8087 code
|
||
endif
|
||
|
||
ifdef __NT__
|
||
OMF equ 1
|
||
COFF equ 0
|
||
ELF equ 0
|
||
_FLAT equ 1
|
||
_STDCALL equ 0
|
||
_RETST0 equ 1
|
||
;_NOCTOR equ 1 ;defined if no static constructors/destructors supported
|
||
_INLINE_8087 equ 1 ;defined if we always generate inline 8087 code
|
||
LONGDOUBLE equ 1 ;defined if memory model supports 80 bit long doubles
|
||
endif
|
||
|
||
ifdef M_XENIX
|
||
OMF equ 1 ;Set to non-zero if OMF object format.
|
||
COFF equ 0 ;Set to non-zero if COFF object format.
|
||
ELF equ 0
|
||
_FLAT equ 0
|
||
_STDCALL equ 0
|
||
_RETST0 equ 0
|
||
endif
|
||
|
||
ifdef M_UNIX
|
||
ifndef OMF
|
||
OMF equ 0 ;Set to non-zero if OMF object format.
|
||
endif
|
||
ifdef M_ELF
|
||
ifndef ELF
|
||
ELF equ 1 ;Set to non-zero if ELF object format.
|
||
endif
|
||
ifndef COFF
|
||
COFF equ 0 ;Set to non-zero if COFF object format.
|
||
endif
|
||
else ;M_ELF
|
||
ifndef ELF
|
||
ELF equ 0 ;Set to non-zero if ELF object format.
|
||
endif
|
||
ifndef COFF
|
||
COFF equ 1 ;Set to non-zero if COFF object format.
|
||
endif
|
||
endif ;M_ELF
|
||
_FLAT equ 0
|
||
_STDCALL equ 0
|
||
_RETST0 equ 0
|
||
endif
|
||
|
||
.ERRNZ OMF AND COFF AND ELF
|
||
.ERRE OMF OR COFF OR ELF
|
||
|
||
I386 equ 1
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
; Macros specific to each memory model in an attempt to make it easier
|
||
; to write memory model independent code.
|
||
; begcode,endcode Use to bracket code sections
|
||
; begdata,enddata Use to bracket data sections
|
||
; begrcode,endrcode Use to bracket real mode code sections
|
||
; begrdata,endrdata Use to bracket real mode data sections
|
||
; (Pharlap DOS386 only)
|
||
; P Offset on EBP to first argument on stack
|
||
; Assuming EBP was pushed.
|
||
; PS Offset on ESP to first argument on stack
|
||
; Assuming nothing was pushed on the stack.
|
||
; ESeqDS 1 if ES == DS at all times
|
||
; FSeqDS 1 if FS == DS at all times
|
||
; GSeqDS 1 if GS == DS at all times
|
||
; SSeqDS 1 if SS == DS at all times
|
||
; SIZEPTR # of bytes in a pointer
|
||
; func Declare a function as NEAR or FAR
|
||
; callm Call function as NEAR or FAR
|
||
; LPTR Large data model?
|
||
; SPTR Small data model?
|
||
|
||
|
||
;Macro for start and end of real mode code segment.
|
||
|
||
begcode_16 macro
|
||
__X386_CODESEG_16 segment para use16 public 'CODE'
|
||
assume ds:__X386_GROUP_16
|
||
assume cs:__X386_CODESEG_16
|
||
endm
|
||
|
||
endcode_16 macro
|
||
__X386_CODESEG_16 ends
|
||
endm
|
||
|
||
begcode macro module
|
||
if _FLAT
|
||
_TEXT segment para use32 public 'CODE'
|
||
assume CS:FLAT,DS:FLAT,SS:FLAT
|
||
else
|
||
_TEXT segment dword public 'CODE'
|
||
assume CS:_TEXT
|
||
endif
|
||
endm
|
||
|
||
endcode macro module
|
||
_TEXT ENDS
|
||
endm
|
||
|
||
begdata macro
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
; Set up segments for data
|
||
; Regular initialized data goes in _DATA
|
||
|
||
_DATA segment dword public 'DATA'
|
||
_DATA ends
|
||
|
||
ifndef _NOCTOR
|
||
;Function pointers to constructors
|
||
if OMF
|
||
XIFCB segment dword public 'DATA'
|
||
XIFCB ends
|
||
XIFU segment dword public 'DATA'
|
||
XIFU ends
|
||
XIFL segment dword public 'DATA'
|
||
XIFL ends
|
||
XIFM segment dword public 'DATA'
|
||
XIFM ends
|
||
XIFCE segment dword public 'DATA'
|
||
XIFCE ends
|
||
XIB segment dword public 'DATA'
|
||
XIB ends
|
||
XI segment dword public 'DATA'
|
||
XI ends
|
||
XIE segment dword public 'DATA'
|
||
XIE ends
|
||
|
||
;Function pointers to destructors
|
||
XCB segment dword public 'DATA'
|
||
XCB ends
|
||
XC segment dword public 'DATA'
|
||
XC ends
|
||
XCE segment dword public 'DATA'
|
||
XCE ends
|
||
|
||
;Constant data, such as switch tables, go here.
|
||
|
||
CONST segment dword public 'CONST'
|
||
CONST ends
|
||
endif
|
||
;Segment for uninitialized data. This is set to 0 by the startup code/OS,
|
||
;so it does not consume room in the executable file.
|
||
|
||
_BSS segment dword public 'BSS'
|
||
_BSS ends
|
||
|
||
if OMF
|
||
;Function pointers to destructors
|
||
XOB segment dword public 'BSS'
|
||
XOB ends
|
||
XO segment dword public 'BSS'
|
||
XO ends
|
||
XOE segment dword public 'BSS'
|
||
XOE ends
|
||
endif
|
||
|
||
if OMF
|
||
ifdef DOS386
|
||
HUGE_BSS segment dword public 'HUGE_BSS'
|
||
HUGE_BSS ends
|
||
endif
|
||
|
||
EEND segment dword public 'ENDBSS'
|
||
EEND ends
|
||
|
||
ifdef DOS386
|
||
STACK segment para stack 'STACK'
|
||
STACK ends
|
||
|
||
DGROUP group _DATA,XIFCB,XIFU,XIFL,XIFM,XIFCE,XOB,XO,XOE,XIB,XI,XIE,XCB,XC,XCE,CONST,_BSS,EEND,STACK
|
||
else
|
||
ifdef __OS2__
|
||
STACK segment para stack 'STACK'
|
||
STACK ends
|
||
|
||
DGROUP group _DATA,XIFCB,XIFU,XIFL,XIFM,XIFCE,XOB,XO,XOE,XIB,XI,XIE,XCB,XC,XCE,CONST,_BSS,EEND,STACK
|
||
else
|
||
ifdef __NT__
|
||
STACK segment para stack 'STACK'
|
||
STACK ends
|
||
|
||
DGROUP group _DATA,XIFCB,XIFU,XIFL,XIFM,XIFCE,XOB,XO,XOE,XIB,XI,XIE,XCB,XC,XCE,CONST,_BSS,EEND,STACK
|
||
else
|
||
DGROUP group _DATA,XIB,XI,XIE,XCB,XC,XCE,CONST,_BSS,EEND
|
||
endif ;__NT__
|
||
|
||
endif ;__OS2__
|
||
endif ;DOS386
|
||
|
||
else ;OMF
|
||
if OMF
|
||
DGROUP group _DATA,XIFCB,XIFU,XIFL,XIFM,XIFCE,XOB,XO,XOE,XIB,XI,XIE,XCB,XC,XCE,CONST,_BSS
|
||
else
|
||
DGROUP group _DATA,_BSS
|
||
endif
|
||
endif
|
||
endif
|
||
|
||
_DATA segment
|
||
if _FLAT
|
||
assume DS:FLAT
|
||
else
|
||
assume DS:DGROUP
|
||
endif
|
||
endm
|
||
|
||
enddata macro
|
||
_DATA ends
|
||
endm
|
||
|
||
P equ 8 ; Offset of start of parameters on the stack frame
|
||
; From EBP assuming EBP was pushed.
|
||
PS equ 4 ; Offset of start of parameters on the stack frame
|
||
|
||
; From ESP assuming EBP was NOT pushed.
|
||
;; For Win32, ESeqDS should be TRUE
|
||
ifdef _WIN32
|
||
ESeqDS equ 1
|
||
else
|
||
ESeqDS equ 0
|
||
endif
|
||
|
||
FSeqDS equ 0
|
||
GSeqDS equ 0
|
||
SSeqDS equ 1
|
||
SIZEPTR equ 4 ; Size of a pointer
|
||
LPTR equ 0
|
||
SPTR equ 1
|
||
LCODE equ 0
|
||
|
||
func macro name
|
||
_&name proc near
|
||
ifndef name
|
||
name equ _&name
|
||
endif
|
||
endm
|
||
|
||
callm macro name
|
||
call _&name
|
||
endm
|
||
|
||
;Macros to replace public, extrn, and endp for C-callable assembly routines,
|
||
; and to define labels: c_label defines labels,
|
||
; c_public replaces public, c_extrn replaces extrn, and c_endp replaces endp
|
||
|
||
c_name macro name
|
||
name equ _&name
|
||
endm
|
||
|
||
c_label macro name
|
||
_&name:
|
||
endm
|
||
|
||
c_public macro a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
|
||
ifnb <a> ;;Check for blank argument
|
||
public _&a
|
||
a equ _&a
|
||
ifnb <b>
|
||
c_public b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
|
||
endif
|
||
endif
|
||
endm
|
||
|
||
c_extrn macro a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
|
||
ifnb <a> ;;Check for blank argument
|
||
extrn _&a:b
|
||
a equ _&a
|
||
ifnb <c>
|
||
c_extrn c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
|
||
endif
|
||
endif
|
||
endm
|
||
|
||
|
||
c_endp macro name
|
||
_&name ENDP
|
||
endm
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
; Define function ctor as a static constructor
|
||
static_ctor macro ctor
|
||
ifndef _NOCTOR
|
||
if 1
|
||
XIFCB segment dword public 'DATA'
|
||
XIFCB ends
|
||
XIFU segment dword public 'DATA'
|
||
;dd ctor
|
||
XIFU ends
|
||
XIFL segment dword public 'DATA'
|
||
;dd ctor
|
||
XIFL ends
|
||
XIFM segment dword public 'DATA'
|
||
if _FLAT
|
||
dd offset FLAT:ctor
|
||
else
|
||
dd ctor
|
||
endif
|
||
XIFM ends
|
||
XIFCE segment dword public 'DATA'
|
||
XIFCE ends
|
||
else
|
||
XIB segment dword public 'DATA'
|
||
XIB ends
|
||
XI segment dword public 'DATA'
|
||
if _FLAT
|
||
dd offset FLAT:ctor
|
||
else
|
||
dd ctor
|
||
endif
|
||
XI ends
|
||
XIE segment dword public 'DATA'
|
||
XIE ends
|
||
endif
|
||
endif
|
||
endm
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
; Define function dtor as a static destructor
|
||
static_dtor macro dtor
|
||
ifndef _NOCTOR
|
||
if 1
|
||
XOB segment dword public 'DATA'
|
||
XOB ends
|
||
XO segment dword public 'DATA'
|
||
if _FLAT
|
||
dd offset FLAT:dtor
|
||
else
|
||
dd dtor
|
||
endif
|
||
XO ends
|
||
XOE segment dword public 'DATA'
|
||
XOE ends
|
||
else
|
||
XCB segment dword public 'DATA'
|
||
XCB ends
|
||
XC segment dword public 'DATA'
|
||
if _FLAT
|
||
dd offset FLAT:dtor
|
||
else
|
||
dd dtor
|
||
endif
|
||
|
||
XC ends
|
||
XCE segment dword public 'DATA'
|
||
XCE ends
|
||
endif
|
||
endif
|
||
endm
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
; Other more or less useful macros
|
||
|
||
;Aligns the code on dword boundary for max speed.
|
||
_align macro
|
||
;MASM 6.0 has a bug where ALIGN 4 produces bogus code when
|
||
;2 or 3 bytes of filler are necessary.
|
||
ifdef @Version
|
||
if @Version eq 600
|
||
if 0
|
||
if (($ - _TEXT) and 3) eq 1
|
||
db 08Bh,0C0h ;MOV EAX,EAX
|
||
nop
|
||
else
|
||
if (($ - _TEXT) and 3) eq 2
|
||
db 08Bh,0C0h ;MOV EAX,EAX
|
||
else
|
||
if (($ - _TEXT) and 3) eq 3
|
||
nop
|
||
endif
|
||
endif
|
||
endif
|
||
endif
|
||
else
|
||
align 4 ;for MASM 5.1
|
||
endif
|
||
else
|
||
align 4 ;for 386ASM
|
||
endif
|
||
endm
|
||
|
||
_push macro list
|
||
irp arg,<list>
|
||
push arg
|
||
endm
|
||
endm
|
||
|
||
_pop macro list
|
||
irp arg,<list>
|
||
pop arg
|
||
endm
|
||
endm
|
||
|
||
_if macro arg1,cond,arg2,lbl
|
||
cmp arg1,arg2
|
||
j&cond lbl
|
||
endm
|
||
|
||
_ifs macro arg1,cond,arg2,lbl
|
||
cmp arg1,arg2
|
||
j&cond short lbl
|
||
endm
|
||
|
||
clr macro list ;clear a register
|
||
irp reg,<list>
|
||
xor reg,reg
|
||
endm
|
||
endm
|
||
|
||
jmps macro lbl
|
||
jmp short lbl
|
||
endm
|
||
|
||
tst macro reg
|
||
test reg,reg
|
||
endm
|
||
|
||
ifndef nobdos
|
||
|
||
ifdef DOS386
|
||
bdos macro func ;DOS system call.
|
||
ifnb <func>
|
||
mov AH,func
|
||
endif
|
||
int 21h
|
||
endm
|
||
endif ;DOS386
|
||
|
||
ifdef X386
|
||
bdos macro func ;DOS system call.
|
||
ifnb <func>
|
||
mov AH,func
|
||
endif
|
||
int 21h
|
||
endm
|
||
endif ;DOS386
|
||
|
||
ifdef M_XENIX
|
||
bdos macro func ; 386 XENIX system call.
|
||
ifnb <func>
|
||
mov EAX,func
|
||
endif
|
||
|
||
db 9ah ; call far 0x7:0
|
||
dd 0
|
||
dw 07h
|
||
endm
|
||
endif ;M_XENIX
|
||
|
||
ifdef M_UNIX
|
||
bdos macro func ; UNIX system call.
|
||
ifnb <func>
|
||
mov EAX,func
|
||
endif
|
||
|
||
db 9ah ; call far 0x7:0
|
||
dd 0
|
||
dw 07h
|
||
endm
|
||
endif ;M_UNIX
|
||
|
||
endif ;nobdos
|
||
|
||
_retf macro val ;force assembler to build a far return
|
||
ifnb <val>
|
||
db 0CAh
|
||
dw val
|
||
else
|
||
db 0CBh
|
||
endif
|
||
endm
|
||
|
||
_ret macro val ;decide whether caller or callee cleans stack
|
||
if _STDCALL
|
||
ret val
|
||
else
|
||
ret
|
||
endif
|
||
endm
|
||
|
||
; Macros to save and restore regs destroyed by a function
|
||
; Give the macro the list of registers used by the function:
|
||
; uses <AX,BX,SI,DI>
|
||
;
|
||
; At exit to function use 'unuse':
|
||
; unuse <DI,SI,BX,AX>
|
||
|
||
uses macro list
|
||
irp reg,<list>
|
||
ifidn <reg>,<ebx> ;Save ebx.
|
||
push reg
|
||
endif
|
||
|
||
ifidn <reg>,<EBX> ;Save EBX (bug in ifidni).
|
||
push reg
|
||
endif
|
||
|
||
ifidn <reg>,<esi> ;Save esi.
|
||
push reg
|
||
endif
|
||
|
||
ifidn <reg>,<ESI>
|
||
push reg
|
||
endif
|
||
|
||
ifidn <reg>,<edi> ;Save edi.
|
||
push reg
|
||
endif
|
||
|
||
ifidn <reg>,<EDI>
|
||
push reg
|
||
endif
|
||
|
||
ifidn <reg>,<bx> ;Save bx.
|
||
push reg
|
||
endif
|
||
|
||
ifidn <reg>,<BX>
|
||
push reg
|
||
endif
|
||
|
||
ifidn <reg>,<si> ;Save si.
|
||
push reg
|
||
endif
|
||
|
||
ifidn <reg>,<SI>
|
||
push reg
|
||
endif
|
||
|
||
ifidn <reg>,<di> ;Save di.
|
||
push reg
|
||
endif
|
||
|
||
ifidn <reg>,<DI>
|
||
push reg
|
||
endif
|
||
|
||
ifidn <reg>,<ds> ;Save ds.
|
||
push reg
|
||
endif
|
||
|
||
ifidn <reg>,<DS>
|
||
push reg
|
||
endif
|
||
|
||
ifidn <reg>,<es> ;Save es.
|
||
push reg
|
||
endif
|
||
|
||
ifidn <reg>,<ES>
|
||
push reg
|
||
endif
|
||
endm
|
||
endm
|
||
|
||
unuse macro list
|
||
irp reg,<list>
|
||
ifidn <reg>,<ebx> ;Restore ebx.
|
||
pop reg
|
||
endif
|
||
|
||
ifidn <reg>,<EBX>
|
||
pop reg
|
||
endif
|
||
|
||
ifidn <reg>,<esi> ;Restore esi.
|
||
pop reg
|
||
endif
|
||
|
||
ifidn <reg>,<ESI>
|
||
pop reg
|
||
endif
|
||
|
||
ifidn <reg>,<edi> ;Restore edi.
|
||
pop reg
|
||
endif
|
||
|
||
ifidn <reg>,<EDI>
|
||
pop reg
|
||
endif
|
||
|
||
ifidn <reg>,<bx> ;Restore bx.
|
||
pop reg
|
||
endif
|
||
|
||
ifidn <reg>,<BX>
|
||
pop reg
|
||
endif
|
||
|
||
ifidn <reg>,<si> ;Restore si.
|
||
pop reg
|
||
endif
|
||
|
||
ifidn <reg>,<SI>
|
||
pop reg
|
||
endif
|
||
|
||
ifidn <reg>,<di> ;Restore di.
|
||
pop reg
|
||
endif
|
||
|
||
ifidn <reg>,<DI>
|
||
pop reg
|
||
endif
|
||
|
||
ifidn <reg>,<ds> ;Restore ds.
|
||
pop reg
|
||
endif
|
||
|
||
ifidn <reg>,<DS>
|
||
pop reg
|
||
endif
|
||
|
||
ifidn <reg>,<es> ;Restore es.
|
||
pop reg
|
||
endif
|
||
|
||
ifidn <reg>,<ES>
|
||
pop reg
|
||
endif
|
||
|
||
endm
|
||
endm
|
||
|
||
|
||
endif ;M_I386
|
||
|
||
; Executable type
|
||
EXE_DOS equ 1 ; MSDOS
|
||
EXE_DOS16RM equ 2 ; Rational 286 DOS Extender
|
||
EXE_ZPM equ 4 ; ZPM 286 DOS Extender
|
||
EXE_PHAR386 equ 8 ; Pharlap 386 DOS Extender
|
||
EXE_DOSX equ 010h ; DOSX 386 DOS Extender
|
||
EXE_WINDOWS equ 020h ; Windows 3
|
||
EXE_OS2 equ 040h ; OS/2 1.x
|
||
EXE_SCOUNIX equ 080h ; SCO Unix
|
||
EXE_OS2_2 equ 100h ; OS/2 2.0
|
||
EXE_WINDOWSNT equ 200h ; Windows NT
|
||
|