; 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 AsmVars Macro varlist IRP var, AsmVar var ENDM ENDM AsmVar Macro var IFNDEF var var = FALSE ENDIF ENDM BREAK ; ; declare a variable external and allocate a size ; AsmVar InstalledData I_NEED MACRO sym,len IF NOT InstalledData DATA SEGMENT WORD PUBLIC 'DATA' IFIDN , EXTRN &sym:WORD ELSE IFIDN , 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 , .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 , ;; 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 , name LABEL WORD I_AM_SIZE = 1 I_AM_LEN = 2 ELSE IFIDN , name LABEL DWORD I_AM_SIZE = 2 I_AM_LEN = 2 ELSE IFIDN , 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 DB I_AM_SIZE*I_AM_LEN DUP (?) ELSE IF NOT InstalledData IRP itm, 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 macro code .xcref MOV AL,code transfer SYS_RET_ERR .cref ENDM .xcref error 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 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 macro x local a .xcref a: RET ret_l = a .cref endm .xcref return BREAK 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 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 .xcref condret BREAK retz macro condret z,nz endm .xcref retz BREAK retnz macro condret nz,z endm .xcref retnz BREAK retc macro condret c,nc endm .xcref retc BREAK retnc macro condret nc,c endm .xcref retnc BREAK context macro r PUSH SS POP r ASSUME r:DOSGROUP endm .xcref context BREAK SaveReg MACRO reglist ;; push those registers IRP reg, ?stackdepth = ?stackdepth + 1 PUSH reg ENDM ENDM .xcref SaveReg BREAK RestoreReg MACRO reglist ;; pop those registers IRP reg, ?stackdepth = ?stackdepth - 1 POP reg ENDM ENDM .xcref RestoreReg BREAK EnterCrit MACRO section Invoke E§ion ENDM LeaveCrit MACRO section Invoke L§ion ENDM Break AsmVars if debug fmt MACRO typ,lev,fmts,args local a,b,c PUSHF IFNB 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, IFIDN , 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 AsmVar Debug,$temp IF debug DOSAssume Macro reg,reglist,message local a,b IFIDN , $temp = 1 ELSE IFIDN , $temp = 0 ELSE %out ***** Invalid DOS register reg in DOSAssume ***** ENDIF ENDIF IRP r, IFIDN , $temp = $temp OR 2 ELSE IFIDN , $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, ASSUME r:DOSGroup ENDM ENDM ELSE DOSAssume Macro reg,reglist,message IRP r, ASSUME r:DOSGroup ENDM ENDM ENDIF BREAK IF DEBUG Assert MACRO kind, objs, message LOCAL a,b IFIDN , CMP objs,0 JZ a fmt <>,<>, a: ELSE IFIDN , CMP objs,0 JNZ a fmt <>,<>, a: ELSE PUSH AX IRP obj, PUSH obj ENDM IF SHAREF MOV AX,OFFSET b ELSE MOV AX,OFFSET DOSGroup:b ENDIF PUSH AX IFIDN , Invoke BUFCheck ENDIF IFIDN , Invoke SFTCheck ENDIF IFIDN , 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 MACRO name,mpx,fn,save,restore IF Installed IFNB SaveReg ENDIF MOV AX,(mpx SHL 8) + fn INT 2Fh IFNB RestoreReg ENDIF ELSE Invoke name ENDIF ENDM Break localvar macro name,length local a ifidn , ?frame = ?frame + 1 a = ?frame name EQU BYTE PTR [BP-a] else ifidn , ?frame = ?frame + 2 a = ?frame name EQU WORD PTR [BP-a] else ifidn , ?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 , a = ?aframe ?aframe = ?aframe + 1 name EQU BYTE PTR [BP+a] else ifidn , a = ?aframe ?aframe = ?aframe + 2 name EQU WORD PTR [BP+a] else ifidn , 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 macro x if x NE 0 %out ***** FATAL error: x <> 0 foobar endif endm