📄 cruntime.inc
字号:
;***
;cruntime.inc - multi-model assembly macros for interfacing to HLLs
;
; Copyright (c) 1988-1997, Microsoft Corporation. All rights reserved.
;
;Purpose:
; This file defines the current memory model being used.
;
;*******************************************************************************
;==============================================================================
;
;Use the following defines to control processor/segment model
;
; -DI86 8086/8088 processor
; -DI286 80286 processor
; -DI386 80386 processor with 32-bit code/data segment
;
; -Dmem_S Small memory model (near code, near data)
; -Dmem_M Medium memory model (far code, near data)
; -Dmem_C Compact memory model (near code, fat data)
; -Dmem_L Large memory model (far code, far data)
;
; -DSS_NEQ_DGROUP SS and DS point to different segments
;
; default is -DI86 -Dmem_S
;
;==============================================================================
;
;The following variables are defined by this file:
; cpu 86, 286, or 386
; sizeC code distance; 1 = far code, 0 = near code
; sizeD data distance; 1 = far data, 0 = near data
; mmodel english name of the memory model, i.e. "Medium"
; ISIZE, LSIZE, NSIZE size of ints, longs, shorts
; FLTSIZE, DBLSIZE, LDBLSIZE size of float, double, long double
; NPSIZE, FPSIZE size of near/far pointers
; CPSIZE, DPSIZE size of code/data pointers
; ISHIFT, LSHIFT bits to shift to convert byte to int/long
;
;The following macros allow easy writing of combined 16/32 bit code:
;
; 16/32 bit registers:
; rax, rbx, rcx, rdx, expand to native registers (rax = eax or ax)
; rsi, rdi, rsp, rbp
; 16/32 bit register instructions:
; JRCXZ jump when rcx is zero
; CBI convert byte to int (al to rax)
; CAXDX convert rax to rax:rdx
; ZXAL, ZXBL, ZXCL, ZXDL zero extend al,bl,cl,dl to rax,rbx,rcx,rdx
; Pointer instructions:
; LPDS, LPES load data pointer with ES or DS
; PDS, PES segment overrides when pointer loaded as above
; PCS, PSS segment override to get at code/stack segment
; LFPDS, LFPES load far pointer with ES or DS
; FPDS, FPES segment overrides when pointer loaded as above
; CPTR data type of code pointer
; CPDIST distance of code (near/far)
; DNPTR, DFPTR define near/far pointer
; DCPTR, DDPTR define code/data pointer
; DCPTR?, DDPTR? define uninitialized code/data pointer
; CPWORD, DPWORD data type of code or data pointer
; Numeric type instructions:
; IWORD, LWORD, SWORD data type of int, long, short
; DINT, DLONG, DSHORT define int, long, short
; DFLOAT, DDOUBLE, DLDOUBLE define float, double, long double
; Offsets:
; codeoffset, dataoffset offsets from code and data segments
; API calls:
; APIDIST distance of API calls (near/far)
; APIEXT ApiName extrn declaration for an API function
;
;The following utility macros are provided:
; codeseg define/declare code segment
; error <msg> stop assembly with message
; display <msg> display a message, unless QUIET defined
; savelist [<reg> ...] init list of regs to be save by 'proc uses'
; _if cond <instruction> assemble instruction only if cond is TRUE
; _ife cond <instruction> assemble instruction only if cond is FALSE
; _ifd symbol <instruction> assemble instruction only if symbol defined
; _ifnd symbol <instruction> assemble instruction only if symbol not defined
;
; lab LabelName assembles to "LabelName:" If DEBUG is defined
; LabelName is made public
;
; JS* (ex. JSE,JSZ,JSB ...) assemble to "je short","jz short","jb short"
;
; Cmacro look alikes
; static* Name, InitialValue, Repeat defines a static variable of type *
; global* Name, InitialValue, Repeat defines a global variable of type *
; label* Name, {PUBLIC,PASCAL,C} defines a label of type *
;
; PUSH16 SegmentReg pushes 16 bits in a use32 segment
; JMPFAR16 label will do a far 16:16 jmp from a use32 segment
;
;==============================================================================
; error <msg> - Output message and generate error
error MACRO msg
if2 ;; only on pass 2 can we generate errors
%out **********************************************************
%out *** E r r o r -- msg
%out **********************************************************
.err
endif
ENDM
; display msg - Output message unless QUIET defined
display MACRO msg
ifndef QUIET ;; only when quiet flag not set
if1 ;; and on pass 1, then display message
%out msg
endif
endif
ENDM
; One line conditionals:
; here we create the capability of writing code lines like
;
; _if sizeD <push ds> as opposed to if sizeD
; push ds
; endif
_if MACRO cond,text
if cond
text
endif
ENDM
_ife MACRO cond,text
ife cond
text
endif
ENDM
_ifd MACRO cond,text
ifdef cond
text
endif
ENDM
_ifnd MACRO cond,text
ifndef cond
text
endif
ENDM
; set windows flag to 0
?WIN equ 0 ; disable windows-specific code
; check for _MT, requires 286 or greater processor
ifdef _MT
ifndef I386
ifndef I286
; _MT implies 286 processor
display <Multi-thread specified - assuming 80286 processor>
I286 equ <>
endif
endif
endif
; Process memory-model arguments
ifdef mem_M
; Medium model
sizeC equ 1
sizeD equ 0
mmodel equ <Medium>
elseifdef mem_C
; Compact model
sizeC equ 0
sizeD equ 1
mmodel equ <Compact>
elseifdef mem_L
; Large model
sizeC equ 1
sizeD equ 1
mmodel equ <Large>
else
; Small model - default
sizeC equ 0
sizeD equ 0
mmodel equ <Small>
endif
; Process processor arguments
ifdef _WIN32
display <Processor: 486/586>
cpu equ 586
.586
elseifdef _POSIX_
display <Processor: 486/586>
cpu equ 586
.586
elseifdef I286
display <Processor: 80286>
cpu equ 286
.286
elseifdef I386
display <Processor: 80386>
cpu equ 386
.386
else
display <Processor: 8086/8088>
cpu equ 86
.8086
endif
; 386 32-bit checking. Currently we are only expecting small model
; 32 bit segments, so we make a few checks to be sure nothing is
; incorrectly being defined.
ifdef I386
if sizeC or sizeD
error <Must use Small memory model for 386 version.>
endif
ifdef _LOAD_DGROUP
error <No loading DGROUP in 386 version.>
endif
ifdef SS_NEQ_DGROUP
error <SS always equals DGROUP in 386 version.>
endif
endif
; Set memory model
% display <Memory model: mmodel>
% .model mmodel, C
;
; *** Temporary Workaround ***
; Currently, MASM will not recognize the 'FLAT' keyword unless it previously
; appears in an 'assume' statement. Presumably, when the '.model FLAT' feature
; is implemented, this will go away. [Use 'gs:' since we never use that
; segment register.
;
ifdef I386
; ensure that MASM recognizes 'FLAT'
assume gs:FLAT
endif
; Define registers:
; Instead of using the "word" registers directly, we will use a set of
; text equates. This will allow you to use the native word size instead of
; hard coded to 16 bit words. We also have some instruction equates for
; instruction with the register type hard coded in.
ifdef I386
rax equ <eax>
rbx equ <ebx>
rcx equ <ecx>
rdx equ <edx>
rdi equ <edi>
rsi equ <esi>
rbp equ <ebp>
rsp equ <esp>
JRCXZ equ <jecxz>
CBI equ <movsx eax, al> ; convert byte to int (al to rax)
CAXDX equ <cdq> ; convert rax to rdx:rax
ZXAL equ <movzx eax, al> ; zero extend al
ZXBL equ <movzx ebx, bl> ; zero extend bl
ZXCL equ <movzx ecx, cl> ; zero extend cl
ZXDL equ <movzx edx, dl> ; zero extend dl
else
rax equ <ax>
rbx equ <bx>
rcx equ <cx>
rdx equ <dx>
rdi equ <di>
rsi equ <si>
rbp equ <bp>
rsp equ <sp>
JRCXZ equ <jcxz>
CBI equ <cbw> ; convert byte to int (al to rax)
CAXDX equ <cwd> ; convert rax to rdx:rax
ZXAL equ <xor ah, ah> ; zero extend al
ZXBL equ <xor bh, bh> ; zero extend bl
ZXCL equ <xor ch, ch> ; zero extend cl
ZXDL equ <xor dh, dh> ; zero extend dl
endif
; The following equates deal with the differences in near versus
; far data pointers, and segment overrides.
;
; Use LPES and PES when loading a default size pointer -- it loads
; a 16-bit pointer register in 286 Small/Medium model,
; a 16-bit pointer register and 16-bit segment register in 8086/286
; Compact/Large model, and a 32-bit pointer register in 386 mode.
;
; Use LFPES and FPES when loading an always far pointer -- it loads a
; 16-bit pointer register and 16-bit segment register in 8086/286,
; all models; a 32-bit pointer register in 386 mode.
if sizeD
LPES equ <les>
LPDS equ <lds>
PDS equ <ds:>
PES equ <es:>
else
LPES equ <mov>
LPDS equ <mov>
PDS equ <>
PES equ <>
endif
ifdef I386
LFPES equ <mov>
LFPDS equ <mov>
FPES equ <>
FPDS equ <>
else
LFPES equ <les>
LFPDS equ <lds>
FPES equ <es:>
FPDS equ <ds:>
endif
if sizeC or @WordSize eq 2
PCS equ <cs:> ; large code model or non-386
else
IF 1 ;*** TEMP 16/32 TESTBED ***
PCS equ <cs:>
ELSE
PCS equ <> ; 386 small code model
ENDIF ;*** END TEMP CODE
endif
ifdef SS_NEQ_DGROUP
PSS equ <ss:> ; SS != DS
else
PSS equ <> ; SS == DS
endif
; Define offset macros:
; The 32-bit segments will not have 'groups'
ifdef I386
codeoffset equ <offset FLAT:>
dataoffset equ <offset FLAT:>
else
codeoffset equ <offset @code:>
dataoffset equ <offset DGROUP:>
endif
; The next set of equates deals with the size of SHORTS, INTS, LONGS, and
; pointers in the 16 and 32 bit versions.
ifdef I386 ;--- 32 bit segment ---
; parameters and locals
IWORD equ <dword>
LWORD equ <dword>
; static storage
DINT equ <dd>
DLONG equ <dd>
DSHORT equ <dw>
; sizes for fixing SP, stepping through tables, etc.
ISIZE equ 4
LSIZE equ 4
SSIZE equ 2
NPSIZE equ 4
FPSIZE equ 4
; bit shift count to convert byte cnt/ptr to int/long cnt/ptr
ISHIFT equ 2 ; byte-to-int shift count
LSHIFT equ 2 ; byte-to-long shift count
; sizes dependent upon memory model. dq -vs- df is not yet clear
DNPTR equ <dd> ; near pointer
DFPTR equ <dd> ; far pointer
DCPTR equ <dd offset FLAT:>; 32 bit offset only
DCPTR? equ <dd> ; No seg override for uninitialized values
CPSIZE equ 4
CPDIST equ <near> ; code pointers are near
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -