; ; 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 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 ENDM ; ; 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 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 ; ; 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 ; ; get a long address in a dword ; long_addr MACRO name .xcref IF2 IFNDEF name EXTRN name:NEAR ENDIF .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 ; ; call the macro chain ; do_ext macro endm PAGE ; ; 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 lbl&_j = a .cref endm BREAK <RETURN - return from a function> return macro local a .xcref a: RET ret_l = a .cref endm BREAK <CONDRET - conditional return> makelab macro l,cc,ncc local a 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 BREAK <CONTEXT - set the DOS context to a particular register> context macro r PUSH SS POP r ASSUME r:DOSGROUP endm