311 lines
6.5 KiB
NASM
311 lines
6.5 KiB
NASM
;
|
||
; Macro file for MSDOS.
|
||
;
|
||
|
||
SUBTTL BREAK a listing into pages and give new subtitles
|
||
PAGE
|
||
BREAK MACRO subtitle
|
||
SUBTTL subtitle
|
||
PAGE
|
||
ENDM
|
||
|
||
BREAK <I_NEED: declare a variable external, if necessary, and allocate a size>
|
||
|
||
;
|
||
; declare a variable external and allocate a size
|
||
;
|
||
I_NEED MACRO sym,len
|
||
CODE ENDS
|
||
DATA SEGMENT BYTE PUBLIC 'DATA'
|
||
|
||
IFIDN <len>,<WORD>
|
||
EXTRN &sym:WORD
|
||
ELSE
|
||
IFIDN <len>,<DWORD>
|
||
EXTRN &sym:DWORD
|
||
ELSE
|
||
EXTRN &sym:BYTE
|
||
ENDIF
|
||
ENDIF
|
||
|
||
DATA ENDS
|
||
CODE SEGMENT BYTE PUBLIC 'CODE'
|
||
ENDM
|
||
|
||
;
|
||
; call a procedure that may be external. The call will be short.
|
||
;
|
||
invoke MACRO name
|
||
&.xcref
|
||
add_ext name,near
|
||
&.cref
|
||
CALL name
|
||
ENDM
|
||
|
||
PAGE
|
||
;
|
||
; jump to a label that may be external. The call will be near.
|
||
;
|
||
transfer MACRO name
|
||
&.xcref
|
||
add_ext name,near
|
||
&.cref
|
||
JUMP name
|
||
ENDM
|
||
|
||
;
|
||
; get a short address in a word
|
||
;
|
||
short_addr MACRO name
|
||
IFDIF <name>,<?>
|
||
&.xcref
|
||
add_ext name,near
|
||
&.cref
|
||
DW OFFSET DOSGROUP:name
|
||
ELSE
|
||
DW ?
|
||
ENDIF
|
||
ENDM
|
||
|
||
;
|
||
; get a long address in a dword
|
||
;
|
||
long_addr MACRO name
|
||
&.xcref
|
||
add_ext name,far
|
||
&.cref
|
||
DD name
|
||
ENDM
|
||
|
||
;
|
||
; declare a PROC near or far but PUBLIC nonetheless
|
||
;
|
||
procedure MACRO name,distance
|
||
PUBLIC name
|
||
name PROC distance
|
||
ENDM
|
||
|
||
PAGE
|
||
;
|
||
; define a data item to be public and of an appropriate size/type
|
||
;
|
||
I_AM MACRO name,size
|
||
PUBLIC name
|
||
|
||
IFIDN <size>,<WORD>
|
||
name DW ?
|
||
ELSE
|
||
IFIDN <size>,<DWORD>
|
||
name DD ?
|
||
ELSE
|
||
IFIDN <size>,<BYTE>
|
||
name DB ?
|
||
ELSE
|
||
name DB size DUP (?)
|
||
ENDIF
|
||
ENDIF
|
||
ENDIF
|
||
ENDM
|
||
|
||
PAGE
|
||
;
|
||
; play games with a possible external. Create a new
|
||
; macro for the symbol and text, and string it together
|
||
; with a central invoker
|
||
;
|
||
|
||
.xcref
|
||
.xcref ?i
|
||
.xcref def_mac
|
||
.xcref ?z0
|
||
.xcref add_ext
|
||
.cref
|
||
|
||
IF1
|
||
?i=0
|
||
ENDIF
|
||
|
||
?z0 macro
|
||
endm
|
||
|
||
;
|
||
; add an external declaration to s with type t if it is not defined
|
||
;
|
||
add_ext macro s,t
|
||
&.xcref
|
||
&.xcref ?&s
|
||
&.cref
|
||
IFNDEF ?&s
|
||
?i = ?i + 1
|
||
def_mac ?z&%?i,?z&%(?i-1),s,t
|
||
ENDIF
|
||
endm
|
||
|
||
;
|
||
; define a macro called that possibly externals s:t and then calls macro n
|
||
;
|
||
def_mac macro m,n,s,t
|
||
&.xcref
|
||
&.xcref ?&s
|
||
&.xcref m
|
||
&.cref
|
||
m macro
|
||
ifndef s
|
||
extrn s:&t
|
||
endif
|
||
purge m
|
||
purge ?&s
|
||
n
|
||
endm
|
||
?&s macro
|
||
&endm
|
||
endm
|
||
|
||
;
|
||
; call the macro chain
|
||
;
|
||
do_ext macro
|
||
&.xcref
|
||
expand_mac ?z%?i
|
||
&.cref
|
||
endm
|
||
|
||
PAGE
|
||
expand_mac macro m
|
||
m
|
||
endm
|
||
|
||
;
|
||
; define an entry in a procedure
|
||
;
|
||
entry macro name
|
||
PUBLIC name
|
||
name:
|
||
endm
|
||
|
||
BREAK <ERROR - print a message and then jump to a label>
|
||
|
||
error macro code
|
||
local a
|
||
.xcref
|
||
MOV AL,code
|
||
transfer SYS_RET_ERR
|
||
.cref
|
||
ENDM
|
||
|
||
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
|
||
a:
|
||
ifndef lbl&_J ; is this the first invocation
|
||
JMP lbl
|
||
ELSE
|
||
IF lbl&_J GE $
|
||
JMP lbl
|
||
ELSE
|
||
IF ($-lbl&_J) GT 126 ; is the jump too far away?
|
||
JMP lbl
|
||
ELSE ; do the short one...
|
||
JMP lbl&_J
|
||
ENDIF
|
||
ENDIF
|
||
ENDIF
|
||
endm
|
||
|
||
BREAK <RETURN - return from a function>
|
||
|
||
return macro
|
||
local a
|
||
.xcref
|
||
a:
|
||
RET
|
||
ret_l = a
|
||
endm
|
||
|
||
BREAK <CONDRET - conditional return>
|
||
|
||
makelab macro l,cc,ncc
|
||
j&ncc a ; j<NCC> a:
|
||
return ; return
|
||
a: ; a:
|
||
ret_&cc = ret_l ; define ret_<CC> to be ret_l
|
||
endm
|
||
|
||
condret macro cc,ncc
|
||
local a,b
|
||
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:
|
||
else
|
||
makelab a,cc,ncc
|
||
endif
|
||
else
|
||
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:
|
||
else
|
||
makelab a,cc,ncc
|
||
endif
|
||
else
|
||
makelab a,cc,ncc
|
||
endif
|
||
endif
|
||
endm
|
||
;condret macro cc,ncc
|
||
; local a,b
|
||
; 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
|
||
|
||
BREAK <RETZ - return if zero, links up shortwise if necessary>
|
||
|
||
retz macro
|
||
condret z,nz
|
||
endm
|
||
|
||
BREAK <RETNZ - return if not zero, links up shortwise if necessary>
|
||
|
||
retnz macro
|
||
condret nz,z
|
||
endm
|
||
|
||
BREAK <RETC - return if carry set, links up shortwise if necessary>
|
||
|
||
retc macro
|
||
condret c,nc
|
||
endm
|
||
|
||
BREAK <RETNC - return if not carry, links up shortwise if necessary>
|
||
|
||
retnc macro
|
||
condret nc,c
|
||
endm
|
||
|