home *** CD-ROM | disk | FTP | other *** search
Text File | 1987-05-22 | 32.6 KB | 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
- ~