home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programming
/
powerprogramming1994.iso
/
progtool
/
microcrn
/
issue_36.arc
/
SYHL.MAC
< prev
next >
Wrap
Text File
|
1987-05-22
|
33KB
|
1,162 lines
comment ~
Porting Macros (file syhl.mac)
This file goes with the article "Porting Assembly Functions". This listing
that appeared in the magazine is excerpted from this file; you should use this
one in your programs and not transcribe the magazine listing.
(C) Copyright 1987 Ken Berry- All rights reserved.
Copies may be made for non-commercial, private use only.
Logic values
~
_T equ 1 ; true
_F equ 0 ; false
comment ~
Process memory model from command line
~
ifdef COM ; ".com program
SYS_C equ _F ; small code
SYS_D equ _F ; small data
SYS_COM equ _T ; ".com" program
else
SYS_COM equ _F ; not ".com" program
ifdef SCSD ; small code, small data
SYS_C equ _F ; small code
SYS_D equ _F ; small data
else
ifdef LCSD ; large code, small data
SYS_C equ _T ; large code
SYS_D equ _F ; small data
else
ifdef SCLD ; small code, large data
SYS_C equ _F ; small code
SYS_D equ _T ; large data
else
ifdef LCLD ; large code, large data
SYS_C equ _T ; large code
SYS_D equ _T ; large data
endif
endif
endif
endif
endif
ifndef SYS_C ; test for no model specified
SYS_C equ _F ; small code
SYS_D equ _F ; small data
SYS_COM equ _F ; not ".com" program
endif
comment ~
Define memory model for _cmplr macro
~
if (SYS_C eq _F) and (SYS_D eq _F)
SYS_SMDL equ _T
SYS_DMDL equ _F
SYS_PMDL equ _F
SYS_LMDL equ _F
endif
if (SYS_C eq _F) and (SYS_D eq _T)
SYS_SMDL equ _F
SYS_DMDL equ _T
SYS_PMDL equ _F
SYS_LMDL equ _F
endif
if (SYS_C eq _T) and (SYS_D eq _F)
SYS_SMDL equ _F
SYS_DMDL equ _F
SYS_PMDL equ _T
SYS_LMDL equ _F
endif
if (SYS_C eq _T) and (SYS_D eq _T)
SYS_SMDL equ _F
SYS_DMDL equ _F
SYS_PMDL equ _F
SYS_LMDL equ _T
endif
comment ~
Process compiler from command line
~
SYS_CPLT equ 1 ; Lattice C 3.0
SYS_CPMS equ 2 ; Microsoft C 4.0
ifndef SYS_CPLR ; test for no compiler specified
ifdef LTC ; Lattice C 3.0
SYS_CPLR equ SYS_CPLT
SYS_CPVR equ 30
else
ifdef MSC ; Microsoft C 4.0
SYS_CPLR equ SYS_CPMS
SYS_CPVR equ 40
endif
endif
ifndef SYS_CPLR
SYS_CPLR equ SYS_CPMS
SYS_CPVR equ 40
endif
endif
comment ~
Macro Parameters
~
.xcref
.xcref ?popn,?argc,?argl,?ldul,?nglclo,?rsv,?fnp,?pass
.xcref ?msc,?ltc,?cmpl,?scs,?sxr
?popn = _F ; procedure open flag
?argc = 0 ; argument count
?argl = 0 ; argument length
?ldul = _F ; leading underline convention off
?nglclo = _F ; positive local offset
?scs = _F ; caller clears stack
?rsv = 0 ; no registers to be saved
?fnp = _F ; variable number of arguments (C protocol)
?sxr = _F ; do not save index registers
if1
?pass = 1 ; define pass 1
else
?pass = 2 ; define pass 2
endif
ifndef ?usrseg ; test for not user defined segments
?usrseg = _F ; indicate user not defining segments
endif
?msc = _F ; not Microsoft C compiler
?ltc = _F ; not Lattice C compiler
?cmpl = _F ; no compiler specified
.cref
comment ~
Compiler Selection
~
; Lattice C
_lc MACRO sd ;; Lattice C structure
if ?cmpl ;; test for compiler already defined
%out compiler already specified
else
if1
%out Lattice C compiler interface
endif
?ldul = _F ;; leading underline convention off
?nglclo = _F ;; positive local offset
?scs = _F ;; caller clears stack
?fnp = _F ;; C protocol
?ltc = _T ;; indicate Lattice C compiler
?cmpl = _T ;; indicate compiler selected
?sxr = _F ;; do not save index registers
ifidn <>,<sd> ;; test for segments not suppressed
_crtseg data,data,word,public,data,dgroup
_crtseg udata,udata,word,public,data,dgroup
_defgrp dgroup
if SYS_SMDL ; test for small code, small data
_crtseg prog,code,byte,public,prog,pgroup
_defgrp pgroup
endif
if SYS_PMDL ; test for large code, small data
_crtseg _code,code,byte,public,code
endif
if SYS_DMDL ; test for small code, large data
_crtseg code,code,byte,public,code,cgroup
_defgrp cgroup
endif
if SYS_LMDL ; test for large code, large data
_crtseg _prog,code,byte,public,prog
endif
endif
_dofst equ offset dgroup:
if SYS_SMDL ; test for small code, small data
_cofst equ offset pgroup:
endif
if SYS_PMDL ; test for large code, small data
_cofst equ offset _code:
endif
if SYS_DMDL ; test for small code, large data
_cofst equ offset code:
endif
if SYS_LMDL ; test for large code, large data
_cofst equ offset _prog:
endif
endif
ENDM
; Microsoft C
_msc MACRO sd ;; Microsoft C structure
if ?cmpl ;; test for compiler already defined
%out compiler already specified
else
if1
%out Microsoft C compiler interface
endif
?ldul = _T ;; leading underline convention on
?nglclo = _T ;; negative local offset
?scs = _F ;; caller clears stack
?fnp = _F ;; C protocol
?msc = _T ;; indicate Microsoft C compiler
?cmpl = _T ;; indicate compiler selected
?sxr = _T ;; save index registers
ifidn <>,<sd> ;; test for segments not suppressed
_crtseg _DATA,data,word,public,DATA,DGROUP
_defgrp DGROUP
_crtseg _TEXT,code,byte,public,CODE ; code segment
endif
_cofst equ offset _TEXT:
_dofst equ offset DGROUP:
endif
ENDM
; compiler selection macro
_cmplr MACRO ng
ife (SYS_CPLR-SYS_CPLT) ;; test for Lattice specified
_lc ng ;; define Lattice C structure
else
ife (SYS_CPLR-SYS_CPMS) ;; test for Microsoft specified
_msc ng ;; define Microsoft C structure
endif
endif
ife ?cmpl ;; test for no compiler specified
if1
%out no compiler specified (default used)
endif
_lc ng ;; define Lattice C structure by default
endif
ifidn <ng>,<> ;; test for segments not suppressed
_assume cs,code
_assume ds,data
endif
if1
if SYS_SMDL ;; s model
%out small code, small data
else
if SYS_PMDL ;; p model
%out large code, small data
else
if SYS_DMDL ;; d model
%out small code, large data
else
if SYS_LMDL ;; l model
%out large code, large data
endif
endif
endif
endif
endif
ENDM
comment ~
Segment Control
~
; create segment
_crtseg MACRO n,ln,t,p,c,g
ifnb <g>
?addseg g,n ;; add segment to group
endif
ifnb <c>
n segment t p '&c' ;; define segment in class
else
n segment t p ;; define independant segment
endif
n ends ;; close segment
?cs1 n,ln
ENDM
?cs1 MACRO n,ln
?b_&ln &MACRO
?cs2 n,ln
n segment
&ENDM
ENDM
?cs2 MACRO n,ln
_ends &MACRO
if2
%out end segment &ln
endif
n ends
&ENDM
ENDM
_begs MACRO ln
if2
%out begin segment &ln
endif
?b_&ln
ENDM
; define group
_defgrp MACRO g
?addseg g ;; define group
ENDM
; add segment to group
?addseg MACRO g,n ;; add segment to group
.xcref
.xcref ?p_&g
.cref
ifndef ?p_&g
?p_&g = 0 ;; define pass control variable
endif
if ?p_&g ne ?pass ;; test for first time this pass
?add_&g &MACRO s
?in_&g <n>,s
&ENDM
?in_&g &MACRO sl,s
ifb <s>
g group sl
else
?add_&g &MACRO ns
?in_&g <sl,s>,ns
&ENDM
endif
&ENDM
?p_&g = ?pass ;; update pass flag
else
?add_&g n
endif
ENDM
; assign segment register
_assume MACRO r,s ;; assign segment register
ifidn <&s>,<data>
assume &r:dgroup ;; set data segment
EXITM
endif
ifidn <&s>,<code>
if ?msc ;; test for Microsoft C structure
assume &r:_TEXT ;; set code segment
EXITM
endif
if ?ltc ;; test for Lattice C structure
if SYS_SMDL ;; test for small code, small data
assume &r:pgroup
EXITM
endif
if SYS_PMDL ;; test for large code, small data
assume &r:cgroup
EXITM
endif
if SYS_DMDL ;; test for small code, large data
assume &r:_code
EXITM
endif
if SYS_LMDL ;; test for large code, large data
assume &r:_prog
EXITM
endif
endif
endif
ifidn <&s>,<udata>
assume &r:dgroup ;; set udata segment
EXITM
endif
ifidn <&s>,<xstck>
assume &r:dgroup ;; set xstck segment
EXITM
endif
assume &r:&s ;; set data segment
ENDM
comment ~
External Names
~
_xb MACRO n ;; byte label
?ex1 <&n>,1,<byte>
ENDM
_xw MACRO n ;; word label
?ex1 <&n>,2,<word>
ENDM
_xd MACRO n ;; double word label
?ex1 <&n>,4,<dword>
ENDM
_xq MACRO n ;; quad word label
?ex1 <&n>,8,<qword>
ENDM
_xt MACRO n ;; ten byte label
?ex1 <&n>,10,<tbyte>
ENDM
_xnp MACRO n ;; near procedure label
?ex1 <&n>,4,<near>
ENDM
_xfp MACRO n ;; far procedure label
?ex1 <&n>,4,<far>
ENDM
_xp MACRO n ;; procedure label
if SYS_C ;; test for large code
?ex1 <&n>,4,<far>
else ;; small code
?ex1 <&n>,2,<near>
endif
ENDM
_xcp MACRO n ;; code pointer label
if SYS_C ;; test for large code
?ex1 <&n>,4,<dword>
else ;; small code
?ex1 <&n>,2,<word>
endif
ENDM
_xdp MACRO n ;; data pointer label
if SYS_D ;; test for large data
?ex1 <&n>,4,<dword>
else ;; small data
?ex1 <&n>,2,<word>
endif
ENDM
; define external name
?ex1 MACRO n,s,t ;; define external name
irp x,<n> ;; scan name list
.xcref
.xcref ?t_&&x
?t_&&x = s ;; set type value
.cref
if ?ldul ;; test for leading underline convention
extrn _&&x:&t ;; declare external name
x equ _&&x ;; define local name
else ;; no leading underline convention
extrn x:&t ;; declare external name
endif
endm
ENDM
comment ~
Static Data
~
; data definition macros
_db MACRO n,i,r,p ;; byte or string
?tp <&n>,1 ;; define type value
?dd <&n>,p,<byte>,<db>,<&i>,<&r> ;; define data
ENDM
_dw MACRO n,i,r,p ;; word
?tp <&n>,2 ;; define type value
?dd <&n>,p,<word>,<dw>,<&i>,<&r> ;; define data
ENDM
_dd MACRO n,i,r,p ;; double word
?tp <&n>,4 ;; define type value
?dd <&n>,p,<dword>,<dd>,<&i>,<&r> ;; define data
ENDM
_dq MACRO n,i,r,p ;; quad word
?tp <&n>,8 ;; define type value
?dd <&n>,p,<qword>,<dq>,<&i>,<&r> ;; define data
ENDM
_dt MACRO n,i,r,p ;; ten byte
?tp <&n>,10 ;; define type value
?dd <&n>,p,<tbyte>,<dt>,<&i>,<&r> ;; define data
ENDM
_dcp MACRO n,i,r,p ;; code pointer
if SYS_C ;; test for large code
_dd <&n>,<&i>,<&r>,<&p> ;; double word pointer
else ;; small code
_dw <&n>,<&i>,<&r>,<&p> ;; word pointer
endif
ENDM
_ddp MACRO n,i,r,p ;; data pointer
if SYS_D ;; test for large data
_dd <&n>,<&i>,<&r>,<&p> ;; double word pointer
else ;; small data
_dw <&n>,<&i>,<&r>,<&p> ;; word pointer
endif
ENDM
; define type symbol
?tp MACRO n,s ;; define type
.xcref
irp x,<n> ;; scan name list
.xcref ?t_&&x
?t_&&x = s ;; set type value
endm
.cref
ENDM
; define data item
?dd MACRO n,p,t,d,i,r ;; define data
irp x,<n> ;; scan name list
ifdif <p>,<> ;; test for public data
if ?ldul ;; test for leading underline convention
public _&&x ;; declare public symbol
_&&x label t ;; define public symbol
else ;; no leading underline
public x ;; declare public symbol
endif
endif
ifb <r> ;; test for no duplication factor
ifb <i> ;; test for no initialization string
x d ? ;; define uninitialized data
else ;; initialization string
x d i ;; define initialized data
endif
else ;; duplication
ifb <i> ;; test for no initialization string
x d r dup (?) ;; define uninitialized data
else ;; initialization string
x d r dup (i) ;; define initialized data
endif
endif
endm ;; end of name list scan
ENDM
comment ~
Procedure Entry/Exit Code
~
; declare procedure
_dclp MACRO n,c ;; declare procedure
.xcref
.xcref ?lclo,?prmo,?sadj,?pcls,?pblc
.cref
if ?popn ;; test for procedure or data segment open
if1
%out procedure open when proc declared "&n"
endif
else ;; no procedure open
?popn = _T ;; indicate procedure open
?lclo = 0 ;; no local storage bytes
?prmo = 0 ;; no parameter storage bytes
?sadj = 4 ;; stack adjustment
?pcls = SYS_C ;; set default procedure class
?pblc = _F ;; set private default
?rsv = 0 ;; indicate no registers to be saved
irp x,<c> ;; scan class list
ifidn <x>,<far> ;; test for far
?pcls = 1 ;; set far class
endif
ifidn <x>,<near> ;; test for near
?pcls = 0 ;; set near class
endif
ifidn <x>,<public> ;; test for public
?pblc = _T ;; indicate public symbol
endif
ifidn <x>,<private> ;; test for private
?pblc = _F ;; indicate private symbol
endif
endm ;; end of class list scan
if ?pcls ;; test for far class
?sadj = ?sadj+2 ;; correct stack adjustment
endif
if ?ldul ;; test for leading underline
if ?pcls ;; test for far class
n label far ;; define symbol
else ;; near class
n label near ;; define symbol
endif
?dclp1 <_&n>,%?pblc,%?pcls ;; continue declaration
else ;; no leading underline
?dclp1 <n>,%?pblc,%?pcls ;; continue declaration
endif
endif
ENDM
; entry code
?dclp1 MACRO n,p,c ;; declare procedure
.xcref
if2
%out begin procedure &n
endif
_begp &MACRO g,x ;; begin procedure
.xcref
?begp1 <n>
?popn = _F ;; indicate no procedure open
?sadj = (?sadj+1) and 0FFFEh ;; for even number of local bytes
if c ;; test for far procedure
n proc far ;; begin procedure
else ;; near procedure
n proc near ;; begin procedure
endif
if p ;; test for public procedure
public n ;; declare public symbol
endif
ifdif <g>,<> ;; test for no code generation
?padj = ?sadj ;; set parameter adjustment
if ?lclo+?prmo ;; test for parameters or locals
if1
%out _begp "&n" no code generated warning
endif
endif
else
ifidn <x>,<> ;; test for index registers to be saved (function)
if ?sxr ;; test for index registers to be saved (language)
push si ;; protect si
push di ;; protect di
endif
endif
ifdef STKCHK ;; test for stack check on entry required
mov ax,-?lclo ;; * test for stack overflow
call sy__ckst ;; *
else ;; no stack check required
push bp ;; protect bp
endif
if ?sxr ;; test for index registers saved
?sadj = ?sadj+4 ;; correct stack adjustment
endif
if ?nglclo ;; test for negative local offset
mov bp,sp ;; establish stack addressability
if ?lclo ;; test for local storage needed
sub sp,?lclo ;; allocate local storage
endif
?padj = ?sadj ;; set parameter adjustment
else ;; positive local offset
if ?lclo ;; test for local storage needed
sub sp,?lclo ;; allocate local storage
endif
mov bp,sp ;; establish stack addressability
?padj = ?sadj+?lclo ;; set parameter adjustment
endif
endif
.cref
purge _begp ;; erase macro
&ENDM
.cref
ENDM
; exit code
?begp1 MACRO n ;; define termination macro
.xcref
_xitp &MACRO x
if ?nglclo ;; test for negative local offset
mov sp,bp ;; deallocate local variables
else ;; positive local offset
if ?lclo ;; test for local storage needed
add sp,?lclo ;; deallocate local storage
endif
endif
pop bp ;; restore bp
pop di ;; restore di
pop si ;; restore si
if ?scs ;; test for subroutine to clear stack
ret ?prmo ;; unload stack & return
else ;; caller clears stack
ret ;; return
endif
&ENDM
_endp &MACRO g,x ;; terminate procedure
.xcref
ifdif <g>,<> ;; test for no code generation
if ?lclo+?prmo ;; test for parameters or locals
if2
%out _begp "&n" no code generated warning
endif
endif
else
_xitp x ;; exit procedure
endif
n endp ;; end of procedure
if2
%out end procedure &n
endif
.cref
purge _endp ;; erase macro
&ENDM
.cref
ENDM
comment ~
Function Arguments
~
; parameter macros
_pb MACRO n ;; byte parameter
?pd n,<byte>,2,1 ;; define byte locator
ENDM
_pw MACRO n ;; word parameter
?pd n,<word>,2,2 ;; define word locator
ENDM
_pd MACRO n ;; double word parameter
irp x,<n> ;; traverse name list
?pd <&&x>,<dword>,0,4 ;; define double word locator
?pd <?o_&&x>,<word>,2,2 ;; define offset locator
?pd <?s_&&x>,<word>,2,2 ;; sefine segment locator
endm
ENDM
_pq MACRO n ;; quad word parameter
?pd n,<qword>,8,8 ;; define quad word locator
ENDM
_pt MACRO n ;; ten byte parameter
?pd n,<tbyte>,10,10 ;; define ten byte locator
ENDM
_pcp MACRO n ;; code pointer parameter
if SYS_C ;; test for large code
_pd n ;; double word pointer
else ;; small code
_pw n ;; word pointer
endif
ENDM
_pdp MACRO n ;; data pointer parameter
if SYS_D ;; test for large data
_pd n ;; double word pointer
else ;; small data
_pw n ;; word pointer
endif
ENDM
; define parameter
?pd MACRO n,t,l,s ;; define parameter locator
if ?popn ;; test for procedure open
.xcref
irp x,<n> ;; traverse name list
?pd1 x,t,%?prmo ;; define argument locator
?prmo = ?prmo+l ;; update parameter offset
.xcref
?t_&&x = s ;; set parameter size
endm
.cref
else ;; no procedure open
%out no proc open- declared parm "&n"
endif
ENDM
?pd1 MACRO x,t,p ;; define argument locator
ife ?fnp ;; test for variable number of arguments (C)
x equ t ptr [bp+?padj+p] ;; define locator
else
x equ t ptr [bp+?padj+?prmo-p] ;; define locator
endif
ENDM
comment ~
Local Storage
~
; local variable macros
_lb MACRO n ;; local byte
?ld n,<byte>,1,1,0 ;; define byte locator
ENDM
_lw MACRO n ;; local word
?ld n,<word>,2,2,1 ;; define word locator
ENDM
_ld MACRO n ;; local double word
irp x,<n> ;; scan name list
?ld <?o_&&x>,<word>,2,2,1 ;; define offset locator
?ld <?s_&&x>,<word>,2,2,0 ;; sefine segment locator
?ld <&&x>,<dword>,0,4,0 ;; define double word locator
endm
ENDM
_lq MACRO n ;; local quad word
?ld n,<qword>,8,8,1 ;; define quad word locator
ENDM
_lt MACRO n ;; local ten byte
?ld n,<tbyte>,10,10,1 ;; define ten byte locator
ENDM
_lcp MACRO n ;; local code pointer
if SYS_C ;; test for large code
_ld n ;; double word pointer
else ;; small code
_lw n ;; word pointer
endif
ENDM
_ldp MACRO n ;; local data pointer
if SYS_D ;; test for large data
_ld n ;; double word pointer
else ;; small data
_lw n ;; word pointer
endif
ENDM
; define local variable
?ld MACRO n,t,l,s,a ;; define local variable locator
if ?popn ;; test for procedure open
.xcref
?lclo = ?lclo+l ;; update local offset
if a ;; test for boundary alignment required
?lclo = ((?lclo+1) and 0FFFEh) ;; force on word boundary
endif
irp x,<n> ;; scan name list
?ld1 x,t,%?lclo ;; define local locator
.xcref ?t_&&x
?t_&&x = s ;; define variable type
endm
.cref
else ;; no procedure open
%out no proc open- declared local "&n"
endif
ENDM
?ld1 MACRO x,t,o ;; define local locator
if ?nglclo ;; test for negative local offset
x equ t ptr [bp-o] ;; define locator
else ;; positive local offset
x equ t ptr [bp+o] ;; define locator
endif
ENDM
comment ~
Labels
~
_lbb MACRO n ;; byte label
?lb1 <&n>,1,<byte>
ENDM
_lbw MACRO n ;; word label
?lb1 <&n>,2,<word>
ENDM
_lbd MACRO n ;; double word label
?lb1 <&n>,4,<dword>
ENDM
_lbq MACRO n ;; quad word label
?lb1 <&n>,8,<qword>
ENDM
_lbt MACRO n ;; ten byte label
?lb1 <&n>,10,<tbyte>
ENDM
_lbnp MACRO n ;; near procedure label
?lb1 <&n>,4,<near>
ENDM
_lbfp MACRO n ;; far procedure label
?lb1 <&n>,4,<far>
ENDM
_lbp MACRO n ;; procedure label
if SYS_C ;; test for large code
?lb1 <&n>,4,<far>
else ;; small code
?lb1 <&n>,2,<near>
endif
ENDM
_lbcp MACRO n ;; code pointer label
if SYS_C ;; test for large code
?lb1 <&n>,4,<dword>
else ;; small code
?lb1 <&n>,2,<word>
endif
ENDM
_lbdp MACRO n ;; data pointer label
if SYS_D ;; test for large data
?lb1 <&n>,4,<dword>
else ;; small data
?lb1 <&n>,2,<word>
endif
ENDM
; define label
?lb1 MACRO n,s,t
.xcref
.xcref ?pblc
.cref
?pblc = _F ;; set private default
irp x,<n> ;; scan name list
ifidn <public>,<&x> ;; test for public keyword
?pblc = _T ;; indicate public symbol
else ;; not public keyword
ifidn <private>,<&x> ;; test for private keyword
?pblc = _F ;; indicate private symbol
else ;; not public nor private keyword
.xcref
.xcref ?t_&&x
?t_&&x = s ;; define symbol type
.cref
x label t ;; define label
if ?pblc ;; test for public symbol
if ?ldul ;; test for leading underline convention
public _&&x ;; declare symbol public
_&&x label t ;; define public symbol
else ;; not leading underline convention
public x ;; declare symbol public
endif
endif
endif
endif
endm ;; end of name list scan
.cref
ENDM
comment ~
Register Control
~
; register names
.xcref
.xcref ?ah,?bh,?ch,?dh,?al,?bl,?cl,?dl,?ax,?bx,?cx,?dx
.xcref ?si,?di,?sp,?bp,?cs,?ss,?ds,?es
.cref
?ah = 1000000000000000b
?al = 0100000000000000b
?ax = 1100000000000000b
?bh = 0010000000000000b
?bl = 0001000000000000b
?bx = 0011000000000000b
?ch = 0000100000000000b
?cl = 0000010000000000b
?cx = 0000110000000000b
?dh = 0000001000000000b
?dl = 0000000100000000b
?dx = 0000001100000000b
?si = 0000000010000000b
?di = 0000000001000000b
?sp = 0000000000100000b
?bp = 0000000000010000b
?cs = 0000000000001000b
?ss = 0000000000000100b
?ds = 0000000000000010b
?es = 0000000000000001b
; define register group to save
_save MACRO r
?rsv = 0 ;; initialize register vector
?save ?rsv,<r> ;; process register list
ENDM
; define register group that is clobbered
_altr MACRO n,r
.xcref
.xcref ?a_&n
.cref
?a_&n = 0 ;; initialize register vector
?save ?a_&n,<r> ;; process register list
ENDM
; create register vector
?save MACRO r,rl
irp x,<rl> ;; scan argument list
ifdef ?&&x ;; semitest for valid register name
r = r or ?&&x ;; update register vector
endif
endm
ENDM
; protect registers
?mpush MACRO r
irp x,<ax,bx,cx,dx,si,di,bp,sp,es,ds,ss,cs>
if r and ?&&x
push x ;; protect register x
endif
endm
ENDM
; restore registers
?mpop MACRO r
irp x,<cs,ss,ds,es,sp,bp,di,si,dx,cx,bx,ax>
if r and ?&&x
pop x ;; restore register x
endif
endm
ENDM
comment ~
Procedure Calls
~
; procedure call
_call MACRO n,a ;; call high level function
.xcref
.xcref ?actr
.cref
ifnb <a> ;; test for parameters specified
_arg <&a> ;; process argument list
endif
?argl = 0 ;; initialize argument length
if ?fnp ;; fixed number of arguments
?actr = 0 ;; initialize argument count
else ;; variable number of arguments (C protocol)
?actr = ?argc ;; initialize argument count
endif
if ?rsv ;; test for registers to be saved
ifdef &a_&n ;; test for altered registers defined
?rsav = ?rsv and ?a_&n ;; define registers to be saved
else
?rsav = ?rsv ;; define registers to be saved
endif
if ?rsav ;; test for registers to be saved
?mpush ?rsav ;; protect registers
endif
endif
if ?fnp ;; fixed number of arguments
rept ?argc ;; scan argument list from front
?actr = ?actr+1 ;; decrement argument counter
?call %?actr ;; put argument on stack
endm
else ;; variable number of arguments (C protocol)
rept ?argc ;; scan argument list from back
?call %?actr ;; put argument on stack
?actr = ?actr-1 ;; decrement argument counter
endm
endif
if ?ldul ;; test for leading underline convention
call _&n ;; call procedure
else ;; no leading underline
call n ;; call procedure
endif
if ?argl ;; test for arguments on stack
if ?scs ;; test for subroutine clears stack
ifdef ?rsav ;; test for registers to be saved
?mpop ?rsav ;; restore registers
endif
else ;; caller clears stack
if ?nglclo ;; test for negative local offset
add sp,?argl ;; unload stack
ifdef ?rsav ;; test for registers to be saved
?mpop ?rsav ;; restore registers
endif
else ;; positve local offset
ifdef ?rsav ;; test for registers to be saved
add sp,?argl ;; uload stack
?mpop ?rsav ;; restore registers
else ;; no registers to be saved
mov sp,bp ;; unload stack
endif
endif
endif
endif
?argc = 0 ;; reset argument count
?argl = 0 ;; reset argument length
ENDM
; put argument i on stack
?call MACRO i ;; put argument on stack
?a_&i ;; expand storage macro
purge ?a_&i ;; purge storage macro
ENDM
; determine arguments
_arg MACRO a ;; process argument list
irp x,<&a> ;; scan argument list
?argc = ?argc+1 ;; increment argument count
?arg1 <&x>,%?argc ;; define parameter store macro
endm
ENDM
; define argument storing macro
?arg1 MACRO n,i ;; process argument
.xcref
.xcref ?a_&i
?a_&i &MACRO ;; store argument
?arg2 n ;; store argument
&ENDM
.cref
ENDM
; store argument on stack
?arg2 MACRO n ;; store argument
?argl = ?argl+2 ;; increment argument length
ifdef ?t_&n ;; test for size defined
ife ?t_&n ;; test for type = 0
push word ptr (n) ;; store word argument on stack
EXITM ;; exit macro
else
ife ?t_&n-1 ;; test for byte (type = 1)
push word ptr (n) ;; store byte argument on stack
EXITM ;; exit macro
else
ife ?t_&n-2 ;; test for word (type = 2)
push word ptr (n) ;; store word argument on stack
EXITM ;; exit macro
else
ife ?t_&n-4 ;; test for double word (type = 4)
?arg2a n ;; store double word argument on stack
EXITM ;; exit macro
else
ife ?t_&n-8 ;; test for quad word (type = 8)
?arg2b n ;; store quad word argument on stack
EXITM ;; exit macro
else
ife ?t_&n-10 ;; test for ten byte (type = 10)
push word ptr (n)+8 ;; store least significant bytes
?arg2b n ;; store quad word argument on stack
EXITM ;; exit macro
endif
endif
endif
endif
endif
endif
else ;; size not defined
push n ;; store argument on stack
endif
ENDM
?arg2a MACRO n
push word ptr (n)+2 ;; * store double word argument on stack
push word ptr (n) ;; *
ENDM
?arg2b MACRO n
push word ptr (n)+6 ;; * store quad word argument on stack
push word ptr (n)+4 ;; *
arg2a n ;; *
ENDM
comment ~
end of Listing 2
~