; ; Microsoft Confidential ; Copyright (C) Microsoft Corporation 1991 ; All Rights Reserved. ; ;** Macro definitions for MSDOS. ; ; Revision history: ; M019 DB 10/26/90 - Added Cmp32 macro. 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 DOSDATA SEGMENT WORD PUBLIC 'DATA' IFIDN , EXTRN &sym:WORD ELSE IFIDN , EXTRN &sym:DWORD ELSE EXTRN &sym:BYTE ENDIF ENDIF DOSDATA 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 DOSCODE: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 name PROC distance ASSUME DS:nothing,ES:nothing ?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:DOSDATA endm .xcref context BREAK SaveReg MACRO reglist ;; push those registers IRP reg, ?stackdepth = ?stackdepth + 1 PUSH reg ENDM ENDM .xcref SaveReg Save MACRO arglist ;; push those arguments IRP arg, ?stackdepth = ?stackdepth + 1 PUSH arg ENDM ENDM .xcref Save BREAK RestoreReg MACRO reglist ;; pop those registers IRP reg, ?stackdepth = ?stackdepth - 1 POP reg ENDM ENDM .xcref RestoreReg Restore MACRO arglist ;; pop those arguments IRP arg, ?stackdepth = ?stackdepth - 1 POP arg ENDM ENDM .xcref Restore 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) DOSDATA segment a db fmts,0 DOSDATA ends MOV AX,OFFSET DOSDATA: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 , push [bp+2] ; MOV AX,[BP+2] ELSE ; MOV AX,item push 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 ;** DOSAssume - Check that a register addresses DOSSEG ; ; DOSAssume reglist, message IF debug DOSAssume Macro reglist,message local a,b $temp = 0 IRP r, IFIDN , $temp = $temp OR 2 ELSE IFIDN , $temp = $temp OR 4 ELSE IFIDN , $temp = $temp OR 1 ELSE %out ***** Invalid register reg in DOSAssume ***** ENDIF ENDIF ENDIF ENDM Invoke SegCheck jmp short a db $temp db message,0 a: IRP r, ASSUME r:DOSDATA ENDM ENDM ELSE DOSAssume Macro reglist,message IRP r, ASSUME r:DOSDATA 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 DOSDATA: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 DOSDATA segment b db Message,0 DOSDATA 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 save_world macro push es invoke save_user_world endm restore_world macro invoke restore_user_world pop es endm ; ; This macro gets the DOS data segment value and puts it in the specified ; segment register. This can only be used in the DOSCODE segment. ; getdseg macro r mov r, cs:[DosDseg] assume r:dosdata endm ; ; This macro does the necessary extrns to allow use of the getdseg macro. ; allow_getdseg macro ifdef ROMDOS extrn BioDataSeg:word bdata segment at 70H extrn DosDataSg:word bdata ends else extrn DosDseg:word endif endm BREAK LJE macro l LJ JE JNE l endm LJNE macro l LJ jne JE l endm LJZ macro l LJE l endm LJNZ macro l LJNE l endm LJC macro l LJ jc JNC l endm LJNC macro l LJ jnc JC l endm LJA macro l LJ ja JNA l endm LJNA macro l LJ jna JA l endm LJB macro l LJ jb JNB l endm LJNB macro l LJ jnb JB l endm LJS macro l LJ js JNS l endm LJNS macro l LJ jns JS l endm LJAE macro l LJ jae JNAE l endm LJBE macro l LJ jbe JNBE l endm LJL macro l LJ jl JNL l endm LJG macro l LJ jg JNG l endm LJLE macro l LJ jle JNLE l endm DLJE macro l DLJ JE JNE l endm DLJNE macro l DLJ jne JE l endm DLJZ macro l DLJE l endm DLJNZ macro l DLJNE l endm DLJC macro l DLJ jc JNC l endm DLJNC macro l DLJ jnc JC l endm DLJA macro l DLJ ja JNA l endm DLJNA macro l DLJ jna JA l endm DLJB macro l DLJ jb JNB l endm DLJNB macro l DLJ jnb JB l endm DLJS macro l DLJ js JNS l endm DLJNS macro l DLJ jns JS l endm DLJAE macro l DLJ jae JNAE l endm DLJBE macro l DLJ jbe JNBE l endm DLJG macro l DLJ jg JNG l endm DLJL macro l DLJ jl JNL l endm DLJLE macro l DLJ jle JNLE l endm ;* LJ - generate long conditional jump ; ; if target preceeds us and is in range just use a short jump ; else use a long jump ; ; LJ ,,