232 lines
5.3 KiB
HTML
232 lines
5.3 KiB
HTML
; ========================================================
|
|
;
|
|
; 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 <LARGE>
|
|
ELSEIFDEF MODEL_MEDIUM
|
|
MEM_MODEL EQU <MEDIUM>
|
|
ELSEIFDEF MODEL_COMPACT
|
|
MEM_MODEL EQU <COMPACT>
|
|
ELSEIFDEF MODEL_SMALL
|
|
MEM_MODEL EQU <SMALL>
|
|
ENDIF
|
|
|
|
|
|
IFNDEF MEM_MODEL
|
|
MEM_MODEL EQU <SMALL>
|
|
ENDIF
|
|
|
|
IFNDEF CALL_TYPE
|
|
CALL_TYPE EQU <C>
|
|
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 <arg1>
|
|
%out <Assume Macro --> Requires at least 1 argument.>
|
|
ENDIF
|
|
|
|
IF @Version GE 600
|
|
IRP X, <arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9>
|
|
IFNB <x>
|
|
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 <DS>
|
|
USES_FPTR_DS EQU <USES DS>
|
|
DS_IF_DATASIZE EQU <DS>
|
|
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 <vSegReg>
|
|
IRP x, <ES,DS,AX,BX,CX,DX,SI,DI>
|
|
IFIDNI <x>,<vSegReg>
|
|
SEG_OK = 1
|
|
ENDIF
|
|
ENDM
|
|
ENDIF
|
|
|
|
;; Error checking on index register
|
|
IFNB <vReg>
|
|
IRP y, <AX,BX,CX,DX,SI,DI>
|
|
IFIDNI <y>,<vReg>
|
|
REG_OK = 1
|
|
ENDIF
|
|
ENDM
|
|
ENDIF
|
|
|
|
;; Error checking on memory pointer
|
|
IFNB <vPtr>
|
|
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 <LoadPtr Macro --> Invalid segment register vSegReg was specified.>
|
|
ENDIF
|
|
|
|
IF REG_OK EQ 0
|
|
%out <LoadPtr Macro --> Invalid register vReg was specified.>
|
|
ENDIF
|
|
|
|
IF PTR_OK EQ 0
|
|
%out <LoadPtr Macro --> 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 <vSegReg>,<DS>
|
|
lds vReg, vPtr
|
|
ELSEIFIDNI <vSegReg>,<ES>
|
|
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 <vSegReg>,<ES>
|
|
push DS
|
|
pop ES
|
|
ENDIF
|
|
;; Load pointer into specified register
|
|
mov vReg, vPtr
|
|
|
|
ENDIF
|
|
|
|
ENDIF
|
|
|
|
ENDM
|
|
|
|
|