📄 cmacros.new
字号:
COMMENT $
CMACROS - assembly macros for interfacing to HLL
(C)Copyright Microsoft Cor. 1990
$
; Revision History
; 6.0 Initial Release of cmacros for MASM 6.0
;
COMMENT $
; Note: There are some differences between this version of CMACROS
; and previous releases. The most signification is the fact
; that locals and parameter names are now scoped to the body
; of a procedure. To help ease this problem we have introduced
; a new directive cRet. This means that the following transformation
; can occur on your source to deal with parameters no referenced
; in the body of a procedure
;
; cProc cProc
; locals,parms locals,parms
; cBegin cBegin
; .... ...
; cEnd cRet
; error code referencing error code referencing
; locals and parms locals and params
; cEnd <nogen>
;
; The major reason for making locals and parameters scoped was
; the percieved benifit of error checking for defined labels in
; the procedure and the addition of codeView information on locals
; and parameters for functions.
$
.xcref ; Get rid of alot of symbols
; ??_out - output the given message to the console unless ?QUIET
; has been specified
;
; usage:
; ??_out <t>
; where:
; <t> is the message to output
??_out macro t
ifndef ?QUIET
echo t
endif
endm
; outif - output msg if name is non-zero. If name is undefined,
; set name =0, else set name to the default value.
;
; usage:
; outif name, defval, onmsg, offmsg
; where:
; name name of symbol
; defval default value to give symobl if not defined.
; if blank, then 0 will be used
; onmsg text to display if symbol is non-zero
; offmsg text to display if symbol is zero
;
outif macro name:req, defval:=<0>, onmsg, offmsg
ifndef name
name = defval
endif
if name
name = 1
ifnb <onmsg>
??_out <! onmsg>
endif
else
ifnb <offmsg>
??_out <! offmsg>
endif
endif
endm
; ??error - output message and generate an assembly time error
;
; usage:
; ??error <t>
; where:
; t is the text to output
;
??error macro msg
echo e r r o r ------ msg ;; to console
.err e r r o r ------ msg ;; forced error by assembler
endm
??_out <cMacros Version 6.00 - 1/1/91>
??_out <Copyright (C) Microsoft Corp. 1990-1991. All rights reserved.>
;
; Determine the memory model for cmacros. Default to small if
; no other model has been specified.
;
ifdef ?SMALL
memS=1
endif
ifdef ?MEDIUM
memM=1
endif
ifdef ?COMPACT
memC=1
endif
ifdef ?LARGE
memL=1
endif
ifdef ?HUGE
memH=1
endif
outif memS,0,<Small Model>
outif memM,0,<Medium Model>
outif memC,0,<Compact Model>
outif memL,0,<Large Model>
outif memH,0,<Huge Model>
memMOD = memS + memM + memL + memC + memH
if memMOD ne 1
if memMOD eq 0
memS=1 ; Assume small model
outif memS,0,<Small Model>
else
??error <must have only 1 memory model selected>
endif
endif
sizec = memM + memL + memH ; Large Code models
sizeC = sizec
sized = memC + memL + memH ; Large Data models
sizeD = sized
;
; Inform user of any other options selected
;
outif ?DF,0,<No segments or groups will be defined>
outif ?DFDATA,0,<No data segments will be defined>
outif ?DFCODE,0,<No code segments will be defined>
outif ?TF,0,<Epilogue sequences will assume valid SP>
outif ?WIN,1,<Windows support>
outif ?COW,0,<Character Windows support>
outif ?PLM,1,<PL/M calling convention>
outif ?NOATOMIC,0,<ATOMIC calling convention>
outif ?NODATA,0,<NODATA module>
ifdef ?CHKSTK
ifdef ?CHKSTKPROC
??_out <! Private stack checking enabled>
else
??_out <! Stack checking enabled>
endif
else
?CHKSTK = 0
endif
ifndef ?DOS5
?DOS5 = 0
endif
;
; Setup some local variables to the Cmacros package
;
??CM_state = 0 ; 0 - inactive, 1-cProc, 2-cBegin,
??CM_RegSaveList textequ <> ; List of saved registers
??CM_ArgList textequ <>
;
; This function is used to paste together two text items to
; get a third text item.
;
??CM_Paste macro arg1:req, arg2:req
exitm <arg1&arg2>
endm
;
; This function is used to create a text macro containning the
; n-th local to a fuction definition.
;
??CM_addLocal macro arg1:req
??CM_Paste(??CM_local, %??CM_localCount) textequ <LOCAL arg1>
??CM_localCount = ??CM_localCount + 1
endm
;
; This function is used to create a text macro containning the
; n-th parameter to a function definition
;
??CM_addParm macro arg1:req
if ??CM_argCount EQ 20
.err <CMACROS.INC: Cannot have more than 20 arguements to a procedure>
endif
??CM_Paste(??CM_arg, %??CM_argCount) textequ <, arg1>
??CM_argCount = ??CM_argCount + 1
endm
;
; This macro creates the prologue code for a cmacro defined function.
;
; Prologue sequences
;
cPrologue macro procname, flags, cbParms, cbLocals, reglist, userparms
?ba=0 ;;not in a procedure
?pu=0 ;;initial public setting
?ia=0 ;;no special prolog/epilog
?rp=0 ;;no register parameters
??CM_UserDoesFrame=0 ;;don't use makeframe
?ff=0 ;;don't force frame setup
?pas=0 ;;process register save list
?pcc=?PLM ;;calling convention (C or PL/M)
;;
;; Look at all of the user parameters and make appropriate decisions
;;
for x,<userparms>
ifdef ??CM_Paste(??_cproc_, x)
??CM_Paste(??_cproc_, x)
else
??error <e r r o r - unknown keyword x>
.err
endif
endm
;;
;; Now start some error checking
;;
if (??CM_Atomic eq 1) and (??CM_NoData eq 0) ;;ATOMIC requires NODATA
??error <ATOMIC specified without NODATA - ATOMIC ignored>
??CM_Atomic = 0 ;;clear the ATOMIC keyword
endif
if flags AND 020h ;;if a far procedure
if ??CM_WinFarProc ;;if windows
ife ??CM_Atomic ;;if not ATOMIC
ife ?COW ;; COW dos not save DS
?ia=2 ;; adjust locals for saved ds
; ?pas = ?pas and (not ?ds) ;;no need for extra save
endif
endif
endif
else
??CM_WinFarProc=0 ;;not a far windows procedure
endif
; ?pas = ?pas and (not (?sp+?cs+?ss)) ;;make no sense to save these
if ??CM_UserDoesFrame ;;don't save these if user frame
; ?pas = ?pas and (not (?bp+?si+?di))
endif
if ??CM_UserDoesFrame ;;if user frame
if ??CM_NoData
??error <NODATA encountered in &n - user frame ignored>
??CM_UserDoesFrame=0
endif
endif
if ??CM_UserDoesFrame ;;if user frame
if ?rp ;;If register parameters
??error <parmR encountered in &n - user frame ignored>
??CM_UserDoesFrame=0
endif
endif
?cpd=0 ;;terminate current proc def
ifidn <g>,<nogen> ;;if nogen, then cannot have locals
if cbLocals + cbParms + ?rp ;; saved regs, or parmRs
??_out <cBegin - possibly invalid use of nogen>
endif
else ;;else must generate a frame
;;
;; Allow the user to specify his own routine which is going to
;; do the frame set-up for this procedure
;;
if ??CM_UserDoesFrame ;;if user frame code specified
?mf c,cbLocals,%?po ;; call user's makeframe
for reg,reglist ;; save specified registers
push reg
endm
else
if ??CM_WinFarProc ;;if a far windows procedure
ife ??CM_NoData ;;if not NODATA,
mov ax,ds ;; then set AX = current ds, and ;@
nop ;; leave room for MOV AX,1234h ;@
endif
ife ??CM_Atomic ;;if not ATOMIC, far frame must be set
ife ?DOS5 ;;if not DOS5, then set far frame flag
inc bp ;; by incrementing the old bp ;@
endif
push bp ;@
mov bp,sp ;@
ife ?COW ;; save DS not needed for CW
push ds ;@
endif
else ;;ATOMIC procedure
if ?ff+cbLocals+cbParms+?rp ;;if any locals or parameters
push bp ;; then must set frame pointer ;@
mov bp,sp ;; to be able to access them ;@
endif
endif
ife ??CM_NoData ;;if not NODATA, then AX should
mov ds,ax ;; have the ds to use ;@
endif
else ;;not windows. use standard prolog
if ?ff+cbLocals+cbParms+?rp ;;if any locals or parameters
push bp ;; then must set frame pointer ;@
mov bp,sp ;; to be able to access them ;@
endif
endif
if ?rp ;;if parmR's, push them before
??CM_UserDoesFrame=0 ;; allocating locals and saving
rept ?rp ;; the autosave registers
uconcat mpush,,?rp,%??CM_UserDoesFrame
??CM_UserDoesFrame=??CM_UserDoesFrame+1
endm
endif
if cbLocals ;;if locals to allocate
if ?CHKSTK ;;if stack checking enabled
ifdef ?CHKSTKPROC ;;if user supplied stack checking
?CHKSTKPROC %cbLocals ;; invoke it with bytes requested
else
mov ax,cbLocals ;;invoke default stack checking ;@
ife cc
call _chkstk ;@
else
call chkstk ;@
endif
endif
else ;;no stack checking
sub sp,cbLocals ;; allocate any local storage ;@
endif
endif
endif
for reg,reglist ;;save autosave registers
push reg
endm
endif ;; No Gen
ifdef ?PROFILE ;;if profiling enabled
if c ;; and a far procedure
call StartNMeas ;; invoke profile start procedure ;@
endif
endif
exitm %(cbLocals+?ia)
endm
;
; This macro will define the epilogue sequences for CMACROS
; functions.
;
; Epilog sequences
cEpilog macro procname, flags, cbParms, cbLocals, reglist, userparms
if ??CM_nogen ;; Nogen the cEnd --
exitm
endif
?ba=0 ;;no longer in a procedure
ifidn <g>,<nogen> ;;if nogen, then cannot have parmRs
if a+r+lc ;; locals, or saved registers
??_out <cEnd - possibly invalid use of nogen>
endif
else ;;else must remove the frame
ifdef ?PROFILE ;;if profiling enabled
if flags AND 020H ;; and a far procedure
call StopNMeas ;; invoke profile stop procedure
endif ;; (doesn't trash DX:AX)
endif ;; ?PROFILE
for reg,reglist ;;restore autosaved registers
pop reg
endm
if ??CM_UserDoesFrame ;;if to use the "makeframe" procedure
db 0c3h ;; near return to user's makeframe @
else
if ??CM_WinFarProc ;;if far win proc, use special epilog
ife ??CM_Atomic ;;if not ATOMIC, bp was pushed
ife ?COW ;; restore DS not needed for CW
if (?TF eq 0) or (cbLocals+?rp) ;;if cannot assume valid sp
lea sp,-2+[bp] ;; or locals or parmR's, get valid SP @
endif
pop ds ;;restore saved ds and bp @
else
if (?TF eq 0) or (cbLocals+?rp) ;;if cannot assume valid sp
mov sp,bp
endif
endif
pop BP ;; @
ife ?DOS5 ;;if not DOS5, bp was
dec BP ;; incremented to mark far frame @
endif
else ;;ATOMIC frame was set up
if memS32
leave
else
if (?TF eq 0) or (cbLocals+?rp) ;;if cannot assume valid sp
mov SP,BP ;; or locals or parmR's, get valid SP @
endif
if cbLocals+cbParms+?rp
pop BP ;@
endif
endif
endif
else ;;non-windows standard epilog
if ?ff+cbLocals+cbParms+?rp ;;if any parameters
if (?TF eq 0) or (cbLocals+?rp) ;;if cannot assume valid SP
mov SP,BP ;; or locals or parmR's, get valid SP;@
endif
pop BP ;@
endif
endif ;; Far Win Proc
ife flags AND 010H ;;if Pascal calling convention
ret cbParms ;; return and remove paramteres ;@
else ;;else
ret ;; return ;@
endif
endif ;; User makes frame
endif ;; noGen
endm
;
; cProc - This macro is used to define the start of a procedure in CMACROS.
;
; PARAMETERS:
; pname - The name of the procedure to be defined. This field is
; required to be present.
; attribs - This is a list of attributes which may be placed on the
; function being defined.
; autoSave - This is an optional list of registers which are to be
; saved and restored during the prologue/epilogue processing
;
cProc macro pname:REQ, attribs, autoSave
IF ??CM_state NE 0 ;; No nesting of functions allowed
.err <CMACROS.INC: Cannot nest procedure definitions>
endif
;
; Setup some state variables to start the procedure definition
;
??CM_state = 1 ;; Set state variable to seen cProc
??CM_ProcName EQU <pname>
??CM_ProcAutoSave EQU <autoSave>
??CM_localCount = 0
??CM_argCount = 0
??CM_langType EQU <>
??CM_WinFarProc=?WIN ;;default far procedure (win or not)
??CM_NoData=?NODATA ;;default NODATA flag
??CM_Atomic=?NOATOMIC ;;default is not ATOMIC
repeat 20 ;; Clear all parameter textmacros
??CM_Paste(??CM_arg, %??CM_argCount) textequ <>
??CM_argCount = ??CM_argCount + 1
endm
??CM_argCount = 0
ife sizec ;; Set the default distance
dist equ <NEAR>
else
dist equ <FAR>
endif
vis equ <> ;; Set the default visibility
for arg,<attribs> ;; Look at the attribute list
ifidn <arg>, <FAR>
dist equ <FAR>
elseifidn <arg>,<NEAR>
dist equ <NEAR>
elseifidn <arg>,<PUBLIC>
vis equ <PUBLIC>
elseifidn <arg>,<PRIVATE>
vis equ <PRIVATE>
elseifidn <arg>,<LOCAL> ;; Ignore -- only for CRT
elseifidn <arg>,<PASCAL>
??CM_langType equ <PASCAL>
elseifidn <arg>,<C>
??CM_langType equ <C>
elseifidn <arg>,<WIN>
??CM_WinFarProc=1
elseifidn <arg>,<NOWIN>
??CM_WinFarProc=0
elseifidn <arg>,<NODATA>
??CM_NoData=1
elseifidn <arg>,<ATOMIC>
??CM_Atomic=1
else
% .err <CMACROS.INC: cProc -- Unknown arguement '&arg'>
endif
endm
option prologue:cPrologue ;; Change to our prologue sequence
option epilogue:none ;; rets from here on are just rets
endm
;
cBegin macro pname
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -