; ======================================================== ; ; MODEL.INC ; ; Copyright (c) 1991 - Microsoft Corp. ; All rights reserved. ; Microsoft Confidential ; ; ; Include file which allows globally controlling the memory ; model of a library of assembly modules. Also contains ; macros for writing MASM 6.0 code which will compile ; under DOS 5.1. ; ; ; johnhe - 01-24-92 ; ; ======================================================================== ; Default to small memory model and C calling conventions if none ; were declared. ; ; ======================================================================== ; Convert old build switches to new type IFDEF MODEL_LARGE MEM_MODEL EQU ELSEIFDEF MODEL_MEDIUM MEM_MODEL EQU ELSEIFDEF MODEL_COMPACT MEM_MODEL EQU ELSEIFDEF MODEL_SMALL MEM_MODEL EQU ENDIF IFNDEF MEM_MODEL MEM_MODEL EQU ENDIF IFNDEF CALL_TYPE CALL_TYPE EQU ENDIF ; ======================================================================== ; The following defines the memory model based on one of four constants ; being defined. If none of the constants have been defined the model ; will default to MODEL_SMALL ; ======================================================================== DOSSEG .MODEL MEM_MODEL,CALL_TYPE ; ======================================================================== ; This macro allows writing code which will assemble with MASM 5.1 or ; 6.0. MASM 6.0 requires an assume statement before using a register ; as the base pointer of a structure. ; ; RegPtr Register:STRUC, Register:STRUC, ... ; ; EXAMPLE: ; ; RegPtr DI:MyStruc ; ; ======================================================================== RegPtr MACRO arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 IFB %out Requires at least 1 argument.> ENDIF IF @Version GE 600 IRP X, IFNB ASSUME x ENDIF ENDM ENDIF ENDM ; ======================================================================== ; Macro which exsplicitly calls a far or near procedure based on the ; current memory model. ; ; call_M PROCEDURE_NAME ; ; ======================================================================== call_M MACRO Function IF @codesize ; Call adjusted for memory model call FAR PTR Function ; FAR call if LARGE, MED, or HUGE ELSE call NEAR PTR Function ; Else NEAR call ENDIF ENDM ; ======================================================================== ; DS_IF_DATASIZE ; ; Equate to allow DS to be pushed on entry to a function if ptrs are ; far. This macro should be used in conjunction with LoadPtr DS,x,x ; to ensure DS will be saved if its destroyed by a far ptr load. ; ; EXAMPLE: ; ; Function PROC USES DI SI ES FPTR_DS, Buffer:PTR, EndBuf:PTR ; ; LoadPtr ES,DI,EndBuf ; LoadPTr DS,SI,BUffer ; ... ; Function ENDP ; ; Function PROC USES_FPTR_DS, Buffer:PTR, EndBuf:PTR ; ; LoadPtr ES,DI,EndBuf ; LoadPTr DS,SI,BUffer ; ... ; Function ENDP ; ; ======================================================================== IF @DATASIZE FPTR_DS EQU USES_FPTR_DS EQU DS_IF_DATASIZE EQU ELSE FPTR_DS EQU <> USES_FPTR_DS EQU <> DS_IF_DATASIZE EQU <> ENDIF ; ======================================================================== ; LoadPtr ; ; Macro to load a pointer based on the memory model that is in use. ; Argument checking is included in the macro and the appropriate ; error message will be displayed. ; ; LoadPtr MACRO vSegReg, vReg, vPtr ; ; vSegReg - Segment register (normally DS or ES but may be any) ; vReg - Any general purpose register (AX,BX,CX,DX,SI,DI) ; vPtr - Pointer to a memory location. ; The value will be treated as a dword ptr in ; LARGE/COMPACT model and word ptr in MEDIUM/SMALL. ; ; ======================================================================== LoadPtr MACRO vSegReg, vReg, vPtr SEG_OK = 0 ;; Variables to specify different errors REG_OK = 0 PTR_OK = 0 ;; Error checking on segment register IFNB IRP x, IFIDNI , SEG_OK = 1 ENDIF ENDM ENDIF ;; Error checking on index register IFNB IRP y, IFIDNI , REG_OK = 1 ENDIF ENDM ENDIF ;; Error checking on memory pointer IFNB PTR_OK = 1 ENDIF ;; If errs found display appropriate message IF (SEG_OK + REG_OK + PTR_OK) NE 3 IF SEG_OK EQ 0 %out Invalid segment register vSegReg was specified.> ENDIF IF REG_OK EQ 0 %out Invalid register vReg was specified.> ENDIF IF PTR_OK EQ 0 %out No memory pointer was specified.> ENDIF .ERR ELSE ;; Start of code in the macro since no errs found IF @DataSize ;; For LARGE & COMPACT models use LDS or LES opcodes IFIDNI , lds vReg, vPtr ELSEIFIDNI , les vReg, vPtr ELSE mov vSegReg, WORD PTR vPtr[2] mov vReg, WORD PTR vPtr ENDIF ELSE ;; If vSegReg == ES we have to set ES to DATA SEG IFIDNI , push DS pop ES ENDIF ;; Load pointer into specified register mov vReg, vPtr ENDIF ENDIF ENDM