MS-DOS/v2.0/source/DOSMAC.ASM
2018-09-21 17:53:34 -07:00

311 lines
6.5 KiB
NASM
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;
; 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