mirror of https://github.com/AR1972/DOS3.3
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
630 lines
10 KiB
630 lines
10 KiB
; SCCSID = @(#)dosmac.asm 1.1 85/04/10
|
|
; SCCSID = @(#)dosmac.asm 1.1 85/04/10
|
|
;
|
|
; Macro file for MSDOS.
|
|
;
|
|
|
|
TRUE EQU 0FFFFh
|
|
FALSE EQU 0
|
|
|
|
SUBTTL BREAK a listing into pages and give new subtitles
|
|
PAGE
|
|
BREAK MACRO subtitle
|
|
SUBTTL subtitle
|
|
PAGE
|
|
ENDM
|
|
.xcref break
|
|
|
|
BREAK <ASMVAR - handle assembly variables once and for all>
|
|
|
|
AsmVars Macro varlist
|
|
IRP var,<varlist>
|
|
AsmVar var
|
|
ENDM
|
|
ENDM
|
|
|
|
AsmVar Macro var
|
|
IFNDEF var
|
|
var = FALSE
|
|
ENDIF
|
|
ENDM
|
|
|
|
BREAK <I_NEED: declare a variable external, if necessary, and allocate a size>
|
|
|
|
;
|
|
; declare a variable external and allocate a size
|
|
;
|
|
AsmVar InstalledData
|
|
I_NEED MACRO sym,len
|
|
IF NOT InstalledData
|
|
DATA SEGMENT WORD PUBLIC 'DATA'
|
|
IFIDN <len>,<WORD>
|
|
EXTRN &sym:WORD
|
|
ELSE
|
|
IFIDN <len>,<DWORD>
|
|
EXTRN &sym:DWORD
|
|
ELSE
|
|
EXTRN &sym:BYTE
|
|
ENDIF
|
|
ENDIF
|
|
DATA ENDS
|
|
ENDIF
|
|
ENDM
|
|
.xcref I_need
|
|
|
|
;
|
|
; call a procedure that may be external. The call will be short.
|
|
;
|
|
invoke MACRO name
|
|
.xcref
|
|
IF2
|
|
IFNDEF name
|
|
EXTRN name:NEAR
|
|
ENDIF
|
|
ENDIF
|
|
.cref
|
|
CALL name
|
|
ENDM
|
|
.xcref invoke
|
|
|
|
PAGE
|
|
;
|
|
; jump to a label that may be external. The jump will be near.
|
|
;
|
|
transfer MACRO name
|
|
.xcref
|
|
IF2
|
|
IFNDEF name
|
|
EXTRN name:NEAR
|
|
ENDIF
|
|
ENDIF
|
|
.cref
|
|
JUMP name
|
|
ENDM
|
|
.xcref transfer
|
|
|
|
;
|
|
; get a short address in a word
|
|
;
|
|
short_addr MACRO name
|
|
IFDIF <name>,<?>
|
|
.xcref
|
|
IF2
|
|
IFNDEF name
|
|
EXTRN name:NEAR
|
|
ENDIF
|
|
ENDIF
|
|
.cref
|
|
DW OFFSET DOSGROUP:name
|
|
ELSE
|
|
DW ?
|
|
ENDIF
|
|
ENDM
|
|
.xcref short_addr
|
|
|
|
;
|
|
; get a long address in a dword
|
|
;
|
|
long_addr MACRO name
|
|
.xcref
|
|
IF2
|
|
IFNDEF name
|
|
EXTRN name:NEAR
|
|
ENDIF
|
|
ENDIF
|
|
.cref
|
|
DD name
|
|
ENDM
|
|
.xcref long_addr
|
|
|
|
;
|
|
; declare a PROC near or far but PUBLIC nonetheless
|
|
;
|
|
.xcref ?frame
|
|
.xcref ?aframe
|
|
.xcref ?stackdepth
|
|
.xcref ?initstack
|
|
?frame = 0 ; initial
|
|
?aframe = 0 ; initial
|
|
?stackdepth = 0 ; initial stack size
|
|
?initstack = 0 ; initial stack size
|
|
|
|
procedure MACRO name,distance
|
|
?frame = 0
|
|
?aframe = 2 ;; remember the pushed BP
|
|
PUBLIC name
|
|
IF1
|
|
;; %OUT name... pass 1
|
|
ENDIF
|
|
IF2
|
|
;; %OUT name... pass 2
|
|
ENDIF
|
|
name PROC distance
|
|
?initstack = ?stackdepth ;; beginning of procedure
|
|
ENDM
|
|
.xcref procedure
|
|
|
|
;
|
|
; end a procedure and check that stack depth is preserved
|
|
;
|
|
EndProc MACRO name, chk
|
|
IFDIF <chk>,<NoCheck> ;; check the stack size
|
|
IF2
|
|
IF ?initstack NE ?stackdepth ;; is it different?
|
|
%OUT ***** Possible stack size error in name *****
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
name ENDP
|
|
ENDM
|
|
.xcref endproc
|
|
PAGE
|
|
;
|
|
; define a data item to be public and of an appropriate size/type
|
|
;
|
|
|
|
I_AM MACRO name,size,init
|
|
;; declare the object public
|
|
PUBLIC name
|
|
;; declare the type of the object
|
|
IFIDN <size>,<WORD>
|
|
name LABEL WORD
|
|
I_AM_SIZE = 1
|
|
I_AM_LEN = 2
|
|
ELSE
|
|
IFIDN <size>,<DWORD>
|
|
name LABEL DWORD
|
|
I_AM_SIZE = 2
|
|
I_AM_LEN = 2
|
|
ELSE
|
|
IFIDN <size>,<BYTE>
|
|
name LABEL BYTE
|
|
I_AM_SIZE = 1
|
|
I_AM_LEN = 1
|
|
ELSE
|
|
name LABEL BYTE
|
|
I_AM_SIZE = size
|
|
I_AM_LEN = 1
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
;; if no initialize then allocate blank storage
|
|
IFB <init>
|
|
DB I_AM_SIZE*I_AM_LEN DUP (?)
|
|
ELSE
|
|
IF NOT InstalledData
|
|
IRP itm,<init>
|
|
IF I_AM_LEN EQ 1
|
|
DB itm
|
|
ELSE
|
|
DW itm
|
|
ENDIF
|
|
I_AM_SIZE = I_AM_SIZE - 1
|
|
ENDM
|
|
IF I_AM_SIZE NE 0
|
|
%out ***** initialization of name not complete *****
|
|
ENDIF
|
|
ELSE
|
|
DB I_AM_SIZE*I_AM_LEN DUP (?)
|
|
ENDIF
|
|
ENDIF
|
|
ENDM
|
|
.xcref I_AM
|
|
.xcref I_AM_SIZE
|
|
.xcref I_AM_LEN
|
|
I_AM_SIZE = 0
|
|
I_AM_LEN = 0
|
|
|
|
PAGE
|
|
|
|
;
|
|
; define an entry in a procedure
|
|
;
|
|
entry macro name
|
|
PUBLIC name
|
|
name:
|
|
endm
|
|
.xcref entry
|
|
|
|
BREAK <ERROR - store an error code then jump to a label>
|
|
|
|
error macro code
|
|
.xcref
|
|
MOV AL,code
|
|
transfer SYS_RET_ERR
|
|
.cref
|
|
ENDM
|
|
.xcref error
|
|
|
|
BREAK <JUMP - real jump that links up shortwise>
|
|
;
|
|
; given a label <lbl> either 2 byte jump to another label <lbl>_J
|
|
; if it is near enough or 3 byte jump to <lbl>
|
|
;
|
|
|
|
jump macro lbl
|
|
local a
|
|
.xcref
|
|
|
|
ifndef lbl&_J ;; is this the first invocation
|
|
a: JMP lbl
|
|
ELSE
|
|
IF (lbl&_J GE $) OR ($-lbl&_J GT 126)
|
|
a: JMP lbl ;; is the jump too far away?
|
|
ELSE
|
|
a: JMP lbl&_J ;; do the short one...
|
|
ENDIF
|
|
ENDIF
|
|
lbl&_j = a
|
|
.cref
|
|
endm
|
|
.xcref jump
|
|
|
|
BREAK <RETURN - return from a function>
|
|
|
|
return macro x
|
|
local a
|
|
.xcref
|
|
a:
|
|
RET
|
|
ret_l = a
|
|
.cref
|
|
endm
|
|
.xcref return
|
|
|
|
BREAK <CONDRET - conditional return>
|
|
|
|
condret macro cc,ncc
|
|
local a
|
|
.xcref
|
|
.xcref a
|
|
.cref
|
|
ifdef ret_l ;; if ret_l is defined
|
|
if (($ - ret_l) le 126) and ($ gt ret_l)
|
|
;; if ret_l is near enough then
|
|
a: j&cc ret_l ;; a: j<CC> to ret_l
|
|
ret_&cc = a ;; define ret_<CC> to be a:
|
|
exitm
|
|
endif
|
|
endif
|
|
ifdef ret_&cc ;; if ret_<CC> defined
|
|
if (($ - ret_&cc) le 126) and ($ gt ret_&cc)
|
|
;; if ret_<CC> is near enough
|
|
a: j&cc ret_&cc ;; a: j<CC> to ret_<CC>
|
|
ret_&cc = a ;; define ret_<CC> to be a:
|
|
exitm
|
|
endif
|
|
endif
|
|
j&ncc a ;; j<NCC> a:
|
|
return ;; return
|
|
a: ;; a:
|
|
ret_&cc = ret_l ;; define ret_<CC> to be ret_l
|
|
endm
|
|
.xcref condret
|
|
|
|
BREAK <RETZ - return if zero, links up shortwise if necessary>
|
|
|
|
retz macro
|
|
condret z,nz
|
|
endm
|
|
.xcref retz
|
|
|
|
BREAK <RETNZ - return if not zero, links up shortwise if necessary>
|
|
|
|
retnz macro
|
|
condret nz,z
|
|
endm
|
|
.xcref retnz
|
|
|
|
BREAK <RETC - return if carry set, links up shortwise if necessary>
|
|
|
|
retc macro
|
|
condret c,nc
|
|
endm
|
|
.xcref retc
|
|
|
|
BREAK <RETNC - return if not carry, links up shortwise if necessary>
|
|
|
|
retnc macro
|
|
condret nc,c
|
|
endm
|
|
.xcref retnc
|
|
|
|
BREAK <CONTEXT - set the DOS context to a particular register>
|
|
|
|
context macro r
|
|
PUSH SS
|
|
POP r
|
|
ASSUME r:DOSGROUP
|
|
endm
|
|
.xcref context
|
|
|
|
BREAK <SaveReg - save a set of registers>
|
|
|
|
SaveReg MACRO reglist ;; push those registers
|
|
IRP reg,<reglist>
|
|
?stackdepth = ?stackdepth + 1
|
|
PUSH reg
|
|
ENDM
|
|
ENDM
|
|
.xcref SaveReg
|
|
|
|
BREAK <RestoreReg - unsave some registers>
|
|
|
|
RestoreReg MACRO reglist ;; pop those registers
|
|
IRP reg,<reglist>
|
|
?stackdepth = ?stackdepth - 1
|
|
POP reg
|
|
ENDM
|
|
ENDM
|
|
.xcref RestoreReg
|
|
|
|
BREAK <Critical section macros>
|
|
|
|
EnterCrit MACRO section
|
|
Invoke E§ion
|
|
ENDM
|
|
|
|
LeaveCrit MACRO section
|
|
Invoke L§ion
|
|
ENDM
|
|
|
|
Break <message - display a message>
|
|
|
|
AsmVars <ShareF,Cargs,Redirector>
|
|
|
|
if debug
|
|
fmt MACRO typ,lev,fmts,args
|
|
local a,b,c
|
|
PUSHF
|
|
IFNB <typ>
|
|
TEST BugTyp,typ
|
|
JZ c
|
|
CMP BugLev,lev
|
|
JB c
|
|
ENDIF
|
|
PUSH AX
|
|
PUSH BP
|
|
MOV BP,SP
|
|
If (not sharef) and (not redirector)
|
|
Table segment
|
|
a db fmts,0
|
|
Table ends
|
|
MOV AX,OFFSET DOSGROUP:a
|
|
else
|
|
jmp short b
|
|
a db fmts,0
|
|
if sharef
|
|
b: mov ax,offset share:a
|
|
else
|
|
b: mov ax,offset netwrk:a
|
|
endif
|
|
endif
|
|
PUSH AX
|
|
cargs = 2
|
|
IRP item,<args>
|
|
IFIDN <AX>,<item>
|
|
MOV AX,[BP+2]
|
|
ELSE
|
|
MOV AX,item
|
|
ENDIF
|
|
PUSH AX
|
|
cargs = cargs + 2
|
|
ENDM
|
|
invoke PFMT
|
|
ADD SP,Cargs
|
|
POP BP
|
|
POP AX
|
|
c:
|
|
POPF
|
|
ENDM
|
|
else
|
|
fmt macro
|
|
endm
|
|
endif
|
|
|
|
Break <DOSAssume - validate assumes>
|
|
|
|
AsmVar Debug,$temp
|
|
|
|
IF debug
|
|
DOSAssume Macro reg,reglist,message
|
|
local a,b
|
|
IFIDN <reg>,<CS>
|
|
$temp = 1
|
|
ELSE
|
|
IFIDN <reg>,<SS>
|
|
$temp = 0
|
|
ELSE
|
|
%out ***** Invalid DOS register reg in DOSAssume *****
|
|
ENDIF
|
|
ENDIF
|
|
IRP r,<reglist>
|
|
IFIDN <r>,<DS>
|
|
$temp = $temp OR 2
|
|
ELSE
|
|
IFIDN <r>,<ES>
|
|
$temp = $temp OR 4
|
|
ELSE
|
|
%out ***** Invalid register reg in DOSAssume *****
|
|
ENDIF
|
|
ENDIF
|
|
ENDM
|
|
PUSH AX
|
|
MOV AX,$temp
|
|
PUSH AX
|
|
IF SHAREF
|
|
MOV AX,OFFSET a
|
|
ELSE
|
|
MOV AX,OFFSET DOSGroup:a
|
|
ENDIF
|
|
PUSH AX
|
|
Invoke SegCheck
|
|
POP AX
|
|
IF NOT SHAREF
|
|
Table SEGMENT
|
|
a DB message,0
|
|
Table ends
|
|
ELSE
|
|
JMP SHORT a
|
|
b DB message,0
|
|
a:
|
|
ENDIF
|
|
IRP r,<reglist>
|
|
ASSUME r:DOSGroup
|
|
ENDM
|
|
ENDM
|
|
ELSE
|
|
DOSAssume Macro reg,reglist,message
|
|
IRP r,<reglist>
|
|
ASSUME r:DOSGroup
|
|
ENDM
|
|
ENDM
|
|
ENDIF
|
|
|
|
BREAK <ASSERT - make assertions about registers>
|
|
|
|
IF DEBUG
|
|
Assert MACRO kind, objs, message
|
|
LOCAL a,b
|
|
IFIDN <kind>,<Z>
|
|
CMP objs,0
|
|
JZ a
|
|
fmt <>,<>,<message>
|
|
a:
|
|
ELSE
|
|
IFIDN <kind>,<NZ>
|
|
CMP objs,0
|
|
JNZ a
|
|
fmt <>,<>,<message>
|
|
a:
|
|
ELSE
|
|
PUSH AX
|
|
IRP obj,<objs>
|
|
PUSH obj
|
|
ENDM
|
|
IF SHAREF
|
|
MOV AX,OFFSET b
|
|
ELSE
|
|
MOV AX,OFFSET DOSGroup:b
|
|
ENDIF
|
|
PUSH AX
|
|
IFIDN <kind>,<ISBUF>
|
|
Invoke BUFCheck
|
|
ENDIF
|
|
IFIDN <kind>,<ISSFT>
|
|
Invoke SFTCheck
|
|
ENDIF
|
|
IFIDN <kind>,<ISDPB>
|
|
Invoke DPBCheck
|
|
ENDIF
|
|
POP AX
|
|
IF SHAREF
|
|
JMP SHORT a
|
|
b DB Message,0
|
|
a:
|
|
ELSE
|
|
Table segment
|
|
b db Message,0
|
|
Table ends
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDM
|
|
ELSE
|
|
Assert Macro
|
|
ENDM
|
|
ENDIF
|
|
|
|
Break <CallInstall - hook to installable pieces>
|
|
|
|
CallInstall MACRO name,mpx,fn,save,restore
|
|
IF Installed
|
|
IFNB <save>
|
|
SaveReg <save>
|
|
ENDIF
|
|
MOV AX,(mpx SHL 8) + fn
|
|
INT 2Fh
|
|
IFNB <restore>
|
|
RestoreReg <restore>
|
|
ENDIF
|
|
ELSE
|
|
Invoke name
|
|
ENDIF
|
|
ENDM
|
|
|
|
Break <Stack frame manipulators>
|
|
|
|
localvar macro name,length
|
|
local a
|
|
ifidn <length>,<BYTE>
|
|
?frame = ?frame + 1
|
|
a = ?frame
|
|
name EQU BYTE PTR [BP-a]
|
|
else
|
|
ifidn <length>,<WORD>
|
|
?frame = ?frame + 2
|
|
a = ?frame
|
|
name EQU WORD PTR [BP-a]
|
|
else
|
|
ifidn <length>,<DWORD>
|
|
?frame = ?frame + 4
|
|
a = ?frame
|
|
name EQU DWORD PTR [BP-a]
|
|
name&l EQU WORD PTR [BP-a]
|
|
name&h EQU WORD PTR [BP-a+2]
|
|
else
|
|
?frame = ?frame + length
|
|
a = ?frame
|
|
name EQU BYTE PTR [BP-a]
|
|
endif
|
|
endif
|
|
endif
|
|
endm
|
|
|
|
enter macro
|
|
push bp
|
|
mov bp,sp
|
|
sub sp,?frame
|
|
endm
|
|
|
|
leave macro
|
|
mov sp,bp
|
|
pop bp
|
|
endm
|
|
|
|
Argvar macro name,length
|
|
local a
|
|
ifidn <length>,<BYTE>
|
|
a = ?aframe
|
|
?aframe = ?aframe + 1
|
|
name EQU BYTE PTR [BP+a]
|
|
else
|
|
ifidn <length>,<WORD>
|
|
a = ?aframe
|
|
?aframe = ?aframe + 2
|
|
name EQU WORD PTR [BP+a]
|
|
else
|
|
ifidn <length>,<DWORD>
|
|
a = ?aframe
|
|
?aframe = ?aframe + 4
|
|
name EQU DWORD PTR [BP+a]
|
|
name&l EQU WORD PTR [BP+a]
|
|
name&h EQU WORD PTR [BP+a+2]
|
|
else
|
|
a = ?aframe
|
|
?aframe = ?aframe + length
|
|
name EQU BYTE PTR [BP+a]
|
|
endif
|
|
endif
|
|
endif
|
|
endm
|
|
|
|
BREAK <errnz - generate compilation errors>
|
|
|
|
errnz macro x
|
|
if x NE 0
|
|
%out ***** FATAL error: x <> 0
|
|
foobar
|
|
endif
|
|
endm
|