; ; Macro file for MSDOS. ; SUBTTL BREAK a listing into pages and give new subtitles PAGE BREAK MACRO subtitle SUBTTL subtitle PAGE ENDM BREAK ; ; declare a variable external and allocate a size ; I_NEED MACRO sym,len CODE ENDS DATA SEGMENT BYTE PUBLIC 'DATA' IFIDN , EXTRN &sym:WORD ELSE IFIDN , 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 , &.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 , name DW ? ELSE IFIDN , name DD ? ELSE IFIDN , 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 macro code local a .xcref MOV AL,code transfer SYS_RET_ERR .cref ENDM BREAK ; ; given a label either 2 byte jump to another label _J ; if it is near enough or 3 byte jump to ; 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 macro local a .xcref a: RET ret_l = a endm BREAK makelab macro l,cc,ncc j&ncc a ; j a: return ; return a: ; a: ret_&cc = ret_l ; define ret_ 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 to ret_l ret_&cc = a ; define ret_ to be a: else makelab a,cc,ncc endif else ifdef ret_&cc ; if ret_ defined if (($ - ret_&cc) le 126) and ($ gt ret_&cc) ; if ret_ is near enough a: j&cc ret_&cc ; a: j to ret_ ret_&cc = a ; define ret_ 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 to ret_l ; ret_&cc = a ; define ret_ to be a: ; exitm ; endif ; endif ; ifdef ret_&cc ; if ret_ defined ; if (($ - ret_&cc) le 126) and ($ gt ret_&cc) ; ; if ret_ is near enough ; a: j&cc ret_&cc ; a: j to ret_ ; ret_&cc = a ; define ret_ to be a: ; exitm ; endif ; endif ; j&ncc a ; j a: ; return ; return ; a: ; a: ; ret_&cc = ret_l ; define ret_ to be ret_l ;endm BREAK retz macro condret z,nz endm BREAK retnz macro condret nz,z endm BREAK retc macro condret c,nc endm BREAK retnc macro condret nc,c endm