home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / microcrn / issue_36.arc / SYHL.MAC < prev    next >
Text File  |  1987-05-22  |  33KB  |  1,162 lines

  1. comment ~
  2. Porting Macros (file syhl.mac)
  3.  
  4. This  file goes with the article "Porting Assembly Functions".    This  listing 
  5. that appeared in the magazine is excerpted from this file;  you should use this 
  6. one in your programs and not transcribe the magazine listing. 
  7.  
  8. (C) Copyright 1987 Ken Berry- All rights reserved.
  9. Copies may be made for non-commercial, private use only.
  10.  
  11. Logic values
  12. ~
  13.  
  14. _T        equ 1          ; true
  15. _F        equ 0          ; false
  16.  
  17. comment ~
  18. Process memory model from command line
  19. ~
  20.  
  21.   ifdef COM              ; ".com program
  22. SYS_C     equ _F         ; small code
  23. SYS_D     equ _F         ; small data
  24. SYS_COM   equ _T         ; ".com" program
  25.   else
  26. SYS_COM   equ _F         ; not ".com" program
  27.  
  28.   ifdef SCSD             ; small code, small data
  29. SYS_C     equ _F         ; small code
  30. SYS_D     equ _F         ; small data
  31.   else
  32.  
  33.   ifdef LCSD             ; large code, small data
  34. SYS_C     equ _T         ; large code
  35. SYS_D     equ _F         ; small data
  36.   else
  37.  
  38.   ifdef SCLD             ; small code, large data
  39. SYS_C     equ _F         ; small code
  40. SYS_D     equ _T         ; large data
  41.   else
  42.  
  43.   ifdef LCLD             ; large code, large data
  44. SYS_C     equ _T         ; large code
  45. SYS_D     equ _T         ; large data
  46.   endif
  47.  
  48.   endif
  49.   endif
  50.   endif
  51.   endif
  52.  
  53.   ifndef SYS_C           ; test for no model specified
  54. SYS_C     equ _F         ; small code
  55. SYS_D     equ _F         ; small data
  56. SYS_COM   equ _F         ; not ".com" program
  57.   endif
  58.  
  59. comment ~
  60. Define memory model for _cmplr macro
  61. ~
  62.  
  63.   if (SYS_C eq _F) and (SYS_D eq _F)
  64. SYS_SMDL  equ _T
  65. SYS_DMDL  equ _F
  66. SYS_PMDL  equ _F
  67. SYS_LMDL  equ _F
  68.   endif
  69.  
  70.   if (SYS_C eq _F) and (SYS_D eq _T)
  71. SYS_SMDL  equ _F
  72. SYS_DMDL  equ _T
  73. SYS_PMDL  equ _F
  74. SYS_LMDL  equ _F
  75.   endif
  76.  
  77.   if (SYS_C eq _T) and (SYS_D eq _F)
  78. SYS_SMDL  equ _F
  79. SYS_DMDL  equ _F
  80. SYS_PMDL  equ _T
  81. SYS_LMDL  equ _F
  82.   endif
  83.  
  84.   if (SYS_C eq _T) and (SYS_D eq _T)
  85. SYS_SMDL  equ _F
  86. SYS_DMDL  equ _F
  87. SYS_PMDL  equ _F
  88. SYS_LMDL  equ _T
  89.   endif
  90.  
  91. comment ~
  92. Process compiler from command line
  93. ~
  94.  
  95. SYS_CPLT  equ 1          ; Lattice C 3.0
  96. SYS_CPMS  equ 2          ; Microsoft C 4.0
  97.  
  98.   ifndef SYS_CPLR        ; test for no compiler specified
  99.     ifdef LTC            ; Lattice C 3.0
  100. SYS_CPLR  equ SYS_CPLT
  101. SYS_CPVR  equ 30
  102.     else
  103.     ifdef MSC            ; Microsoft C 4.0
  104. SYS_CPLR  equ SYS_CPMS
  105. SYS_CPVR  equ 40
  106.     endif
  107.     endif
  108.     ifndef SYS_CPLR
  109. SYS_CPLR  equ SYS_CPMS
  110. SYS_CPVR  equ 40
  111.     endif
  112.   endif
  113.  
  114. comment ~
  115. Macro Parameters
  116. ~
  117.  
  118. .xcref
  119. .xcref ?popn,?argc,?argl,?ldul,?nglclo,?rsv,?fnp,?pass
  120. .xcref ?msc,?ltc,?cmpl,?scs,?sxr
  121. ?popn     = _F           ; procedure open flag
  122. ?argc     = 0            ; argument count
  123. ?argl     = 0            ; argument length
  124. ?ldul     = _F           ; leading underline convention off
  125. ?nglclo   = _F           ; positive local offset
  126. ?scs      = _F           ; caller clears stack
  127. ?rsv      = 0            ; no registers to be saved
  128. ?fnp      = _F           ; variable number of arguments (C protocol)
  129. ?sxr      = _F           ; do not save index registers
  130.   if1
  131. ?pass     = 1            ; define pass 1
  132.   else
  133. ?pass     = 2            ; define pass 2
  134.   endif
  135.   ifndef ?usrseg         ; test for not user defined segments
  136. ?usrseg   = _F           ; indicate user not defining segments
  137.   endif
  138. ?msc      = _F           ; not Microsoft C compiler
  139. ?ltc      = _F           ; not Lattice C compiler
  140. ?cmpl     = _F           ; no compiler specified
  141. .cref
  142.  
  143. comment ~
  144. Compiler Selection
  145. ~
  146.  
  147. ; Lattice C
  148.  
  149. _lc       MACRO sd       ;; Lattice C structure
  150.   if ?cmpl               ;; test for compiler already defined
  151. %out compiler already specified
  152.   else
  153.     if1
  154. %out Lattice C compiler interface
  155.     endif
  156. ?ldul     = _F           ;; leading underline convention off
  157. ?nglclo   = _F           ;; positive local offset
  158. ?scs      = _F           ;; caller clears stack
  159. ?fnp      = _F           ;; C protocol
  160. ?ltc      = _T           ;; indicate Lattice C compiler
  161. ?cmpl     = _T           ;; indicate compiler selected
  162. ?sxr      = _F           ;; do not save index registers
  163.     ifidn <>,<sd>        ;; test for segments not suppressed
  164.           _crtseg data,data,word,public,data,dgroup
  165.           _crtseg udata,udata,word,public,data,dgroup
  166.           _defgrp dgroup
  167.       if SYS_SMDL        ; test for small code, small data
  168.           _crtseg prog,code,byte,public,prog,pgroup
  169.           _defgrp pgroup
  170.       endif
  171.       if SYS_PMDL        ; test for large code, small data
  172.           _crtseg _code,code,byte,public,code
  173.       endif
  174.       if SYS_DMDL        ; test for small code, large data
  175.           _crtseg code,code,byte,public,code,cgroup
  176.           _defgrp cgroup
  177.       endif
  178.       if SYS_LMDL        ; test for large code, large data
  179.           _crtseg _prog,code,byte,public,prog
  180.       endif
  181.     endif
  182. _dofst    equ offset dgroup:
  183.     if SYS_SMDL          ; test for small code, small data
  184. _cofst    equ offset pgroup:
  185.     endif
  186.     if SYS_PMDL          ; test for large code, small data
  187. _cofst    equ offset _code:
  188.     endif
  189.     if SYS_DMDL          ; test for small code, large data
  190. _cofst    equ offset code:
  191.     endif
  192.     if SYS_LMDL          ; test for large code, large data
  193. _cofst    equ offset _prog:
  194.     endif
  195.   endif
  196.           ENDM
  197.  
  198. ; Microsoft C 
  199.  
  200. _msc      MACRO sd       ;; Microsoft C structure
  201.   if ?cmpl               ;; test for compiler already defined
  202. %out compiler already specified
  203.   else
  204.     if1
  205. %out Microsoft C compiler interface
  206.     endif
  207. ?ldul     = _T           ;; leading underline convention on
  208. ?nglclo   = _T           ;; negative local offset
  209. ?scs      = _F           ;; caller clears stack
  210. ?fnp      = _F           ;; C protocol
  211. ?msc      = _T           ;; indicate Microsoft C compiler
  212. ?cmpl     = _T           ;; indicate compiler selected
  213. ?sxr      = _T           ;; save index registers
  214.     ifidn <>,<sd>        ;; test for segments not suppressed
  215.           _crtseg _DATA,data,word,public,DATA,DGROUP
  216.           _defgrp DGROUP
  217.           _crtseg _TEXT,code,byte,public,CODE ; code segment
  218.     endif
  219. _cofst    equ offset _TEXT:
  220. _dofst    equ offset DGROUP:
  221.   endif
  222.           ENDM
  223.  
  224. ; compiler selection macro
  225.  
  226. _cmplr    MACRO ng
  227.   ife (SYS_CPLR-SYS_CPLT) ;; test for Lattice specified
  228.           _lc ng         ;; define Lattice C structure
  229.   else
  230.   ife (SYS_CPLR-SYS_CPMS) ;; test for Microsoft specified
  231.           _msc ng        ;; define Microsoft C structure
  232.   endif
  233.   endif
  234.   ife ?cmpl              ;; test for no compiler specified
  235.     if1
  236. %out no compiler specified (default used)
  237.     endif
  238.           _lc ng         ;; define Lattice C structure by default
  239.   endif
  240.   ifidn <ng>,<>          ;; test for segments not suppressed
  241.           _assume cs,code
  242.           _assume ds,data
  243.   endif
  244.   if1
  245.     if SYS_SMDL          ;; s model
  246. %out small code, small data
  247.     else
  248.     if SYS_PMDL          ;; p model
  249. %out large code, small data
  250.     else
  251.     if SYS_DMDL          ;; d model
  252. %out small code, large data
  253.     else
  254.     if SYS_LMDL          ;; l model
  255. %out large code, large data
  256.     endif
  257.     endif
  258.     endif
  259.     endif
  260.   endif
  261.           ENDM
  262.  
  263. comment ~
  264. Segment Control
  265. ~
  266.  
  267. ; create segment
  268.  
  269. _crtseg   MACRO n,ln,t,p,c,g
  270.   ifnb <g>
  271.           ?addseg g,n    ;; add segment to group
  272.   endif
  273.   ifnb <c>
  274. n         segment t p '&c' ;; define segment in class
  275.   else
  276. n         segment t p    ;; define independant segment
  277.   endif
  278. n         ends           ;; close segment
  279.           ?cs1 n,ln
  280.           ENDM
  281.  
  282. ?cs1      MACRO n,ln
  283. ?b_&ln    &MACRO
  284.           ?cs2 n,ln
  285. n         segment
  286.           &ENDM
  287.           ENDM
  288.  
  289. ?cs2      MACRO n,ln
  290. _ends     &MACRO
  291.   if2
  292. %out end segment &ln
  293.   endif
  294. n         ends
  295.           &ENDM
  296.           ENDM
  297.  
  298. _begs     MACRO ln
  299.   if2
  300. %out begin segment &ln
  301.   endif
  302.           ?b_&ln
  303.           ENDM
  304.  
  305. ; define group
  306.  
  307. _defgrp   MACRO g
  308.           ?addseg g      ;; define group
  309.           ENDM
  310.  
  311. ; add segment to group
  312.  
  313. ?addseg   MACRO g,n      ;; add segment to group
  314. .xcref
  315. .xcref ?p_&g
  316. .cref
  317.   ifndef ?p_&g
  318. ?p_&g     = 0            ;; define pass control variable
  319.   endif
  320.   if ?p_&g ne ?pass      ;; test for first time this pass
  321. ?add_&g   &MACRO s
  322.           ?in_&g <n>,s
  323.           &ENDM
  324. ?in_&g    &MACRO sl,s
  325.     ifb <s>
  326. g         group sl
  327.     else
  328. ?add_&g   &MACRO ns
  329.           ?in_&g <sl,s>,ns
  330.           &ENDM
  331.     endif
  332.           &ENDM
  333. ?p_&g     = ?pass        ;; update pass flag
  334.   else
  335.           ?add_&g n
  336.   endif
  337.           ENDM
  338.  
  339. ; assign segment register
  340.  
  341. _assume   MACRO r,s      ;; assign segment register
  342.   ifidn <&s>,<data>
  343.           assume &r:dgroup ;; set data segment
  344.           EXITM
  345.   endif
  346.   ifidn <&s>,<code>
  347.     if ?msc              ;; test for Microsoft C structure
  348.           assume &r:_TEXT ;; set code segment
  349.           EXITM
  350.     endif
  351.     if ?ltc              ;; test for Lattice C structure
  352.       if SYS_SMDL        ;; test for small code, small data
  353.           assume &r:pgroup
  354.           EXITM
  355.       endif
  356.       if SYS_PMDL        ;; test for large code, small data
  357.           assume &r:cgroup
  358.           EXITM
  359.       endif
  360.       if SYS_DMDL        ;; test for small code, large data
  361.           assume &r:_code
  362.           EXITM
  363.       endif
  364.       if SYS_LMDL        ;; test for large code, large data
  365.           assume &r:_prog
  366.           EXITM
  367.       endif
  368.     endif
  369.   endif
  370.   ifidn <&s>,<udata>
  371.           assume &r:dgroup ;; set udata segment
  372.           EXITM
  373.   endif
  374.   ifidn <&s>,<xstck>
  375.           assume &r:dgroup ;; set xstck segment
  376.           EXITM
  377.   endif
  378.           assume &r:&s   ;; set data segment
  379.           ENDM
  380.  
  381. comment ~
  382. External Names
  383. ~
  384.  
  385. _xb       MACRO n        ;; byte label
  386.           ?ex1 <&n>,1,<byte>
  387.           ENDM
  388.  
  389. _xw       MACRO n        ;; word label
  390.           ?ex1 <&n>,2,<word>
  391.           ENDM
  392.  
  393. _xd       MACRO n        ;; double word label
  394.           ?ex1 <&n>,4,<dword>
  395.           ENDM
  396.  
  397. _xq       MACRO n        ;; quad word label
  398.           ?ex1 <&n>,8,<qword>
  399.           ENDM
  400.  
  401. _xt       MACRO n        ;; ten byte label
  402.           ?ex1 <&n>,10,<tbyte>
  403.           ENDM
  404.  
  405. _xnp      MACRO n        ;; near procedure label
  406.           ?ex1 <&n>,4,<near>
  407.           ENDM
  408.  
  409. _xfp      MACRO n        ;; far procedure label
  410.           ?ex1 <&n>,4,<far>
  411.           ENDM
  412.  
  413. _xp       MACRO n        ;; procedure label
  414.   if SYS_C               ;; test for large code
  415.           ?ex1 <&n>,4,<far>
  416.   else                   ;; small code
  417.           ?ex1 <&n>,2,<near>
  418.   endif
  419.           ENDM
  420.  
  421. _xcp      MACRO n        ;; code pointer label
  422.   if SYS_C               ;; test for large code
  423.           ?ex1 <&n>,4,<dword>
  424.   else                   ;; small code
  425.           ?ex1 <&n>,2,<word>
  426.   endif
  427.           ENDM
  428.  
  429. _xdp      MACRO n        ;; data pointer label
  430.   if SYS_D               ;; test for large data
  431.           ?ex1 <&n>,4,<dword>
  432.   else                   ;; small data
  433.           ?ex1 <&n>,2,<word>
  434.   endif
  435.           ENDM
  436.  
  437. ; define external name
  438.  
  439. ?ex1      MACRO n,s,t    ;; define external name
  440.   irp x,<n>              ;; scan name list
  441. .xcref
  442. .xcref ?t_&&x
  443. ?t_&&x    = s            ;; set type value
  444. .cref
  445.     if ?ldul             ;; test for leading underline convention
  446.           extrn _&&x:&t  ;; declare external name
  447. x         equ _&&x       ;; define local name
  448.     else                 ;; no leading underline convention
  449.           extrn x:&t     ;; declare external name
  450.     endif
  451.   endm
  452.           ENDM
  453.  
  454. comment ~
  455. Static Data
  456. ~
  457.  
  458. ; data definition macros
  459.  
  460. _db       MACRO n,i,r,p  ;; byte or string
  461.           ?tp <&n>,1     ;; define type value
  462.           ?dd <&n>,p,<byte>,<db>,<&i>,<&r> ;; define data
  463.           ENDM
  464.  
  465. _dw       MACRO n,i,r,p  ;; word
  466.           ?tp <&n>,2     ;; define type value
  467.           ?dd <&n>,p,<word>,<dw>,<&i>,<&r> ;; define data
  468.           ENDM
  469.  
  470. _dd       MACRO n,i,r,p  ;; double word
  471.           ?tp <&n>,4     ;; define type value
  472.           ?dd <&n>,p,<dword>,<dd>,<&i>,<&r> ;; define data
  473.           ENDM
  474.  
  475. _dq       MACRO n,i,r,p  ;; quad word
  476.           ?tp <&n>,8     ;; define type value
  477.           ?dd <&n>,p,<qword>,<dq>,<&i>,<&r> ;; define data
  478.           ENDM
  479.  
  480. _dt       MACRO n,i,r,p  ;; ten byte
  481.           ?tp <&n>,10    ;; define type value
  482.           ?dd <&n>,p,<tbyte>,<dt>,<&i>,<&r> ;; define data
  483.           ENDM
  484.  
  485. _dcp      MACRO n,i,r,p  ;; code pointer
  486.   if SYS_C               ;; test for large code
  487.           _dd <&n>,<&i>,<&r>,<&p> ;; double word pointer
  488.   else                   ;; small code
  489.           _dw <&n>,<&i>,<&r>,<&p> ;; word pointer
  490.   endif
  491.           ENDM
  492.  
  493. _ddp      MACRO n,i,r,p  ;; data pointer
  494.   if SYS_D               ;; test for large data
  495.           _dd <&n>,<&i>,<&r>,<&p> ;; double word pointer
  496.   else                   ;; small data
  497.           _dw <&n>,<&i>,<&r>,<&p> ;; word pointer
  498.   endif
  499.           ENDM
  500.  
  501. ; define type symbol
  502.  
  503. ?tp       MACRO n,s      ;; define type
  504. .xcref
  505.   irp x,<n>              ;; scan name list
  506. .xcref ?t_&&x
  507. ?t_&&x    = s            ;; set type value
  508.   endm
  509. .cref
  510.           ENDM
  511.  
  512. ; define data item
  513.  
  514. ?dd       MACRO n,p,t,d,i,r ;; define data
  515.   irp x,<n>              ;; scan name list
  516.     ifdif <p>,<>         ;; test for public data
  517.       if ?ldul           ;; test for leading underline convention
  518.           public _&&x    ;; declare public symbol
  519. _&&x      label t        ;; define public symbol
  520.       else               ;; no leading underline
  521.           public x       ;; declare public symbol
  522.       endif
  523.     endif
  524.     ifb <r>              ;; test for no duplication factor
  525.       ifb <i>            ;; test for no initialization string
  526. x         d ?            ;; define uninitialized data
  527.       else               ;; initialization string
  528. x         d i            ;; define initialized data
  529.       endif
  530.     else                 ;; duplication
  531.       ifb <i>            ;; test for no initialization string
  532. x         d r dup (?)    ;; define uninitialized data
  533.       else               ;; initialization string
  534. x         d r dup (i)    ;; define initialized data
  535.       endif
  536.     endif
  537.   endm                   ;; end of name list scan
  538.           ENDM
  539.  
  540. comment ~
  541. Procedure Entry/Exit Code
  542. ~
  543.  
  544. ; declare procedure
  545.  
  546. _dclp     MACRO n,c      ;; declare procedure
  547. .xcref
  548. .xcref ?lclo,?prmo,?sadj,?pcls,?pblc
  549. .cref
  550.   if ?popn               ;; test for procedure or data segment open
  551.     if1
  552. %out procedure open when proc declared "&n"
  553.     endif
  554.   else                   ;; no procedure open
  555. ?popn     = _T           ;; indicate procedure open
  556. ?lclo     = 0            ;; no local storage bytes
  557. ?prmo     = 0            ;; no parameter storage bytes
  558. ?sadj     = 4            ;; stack adjustment
  559. ?pcls     = SYS_C        ;; set default procedure class
  560. ?pblc     = _F           ;; set private default
  561. ?rsv      = 0            ;; indicate no registers to be saved
  562.     irp x,<c>            ;; scan class list
  563.       ifidn <x>,<far>    ;; test for far
  564. ?pcls     = 1            ;; set far class
  565.       endif
  566.       ifidn <x>,<near>   ;; test for near
  567. ?pcls     = 0            ;; set near class
  568.       endif
  569.       ifidn <x>,<public> ;; test for public
  570. ?pblc     = _T           ;; indicate public symbol
  571.       endif
  572.       ifidn <x>,<private> ;; test for private
  573. ?pblc     = _F           ;; indicate private symbol
  574.       endif
  575.     endm                 ;; end of class list scan
  576.     if ?pcls             ;; test for far class
  577. ?sadj     = ?sadj+2      ;; correct stack adjustment
  578.     endif
  579.     if ?ldul             ;; test for leading underline
  580.       if ?pcls           ;; test for far class
  581. n         label far      ;; define symbol
  582.       else               ;; near class
  583. n         label near     ;; define symbol
  584.       endif
  585.           ?dclp1 <_&n>,%?pblc,%?pcls ;; continue declaration
  586.     else                 ;; no leading underline
  587.           ?dclp1 <n>,%?pblc,%?pcls ;; continue declaration
  588.     endif
  589.   endif
  590.           ENDM
  591.  
  592. ; entry code
  593.  
  594. ?dclp1    MACRO n,p,c    ;; declare procedure
  595. .xcref
  596.   if2
  597. %out begin procedure &n
  598.   endif
  599. _begp     &MACRO g,x     ;; begin procedure
  600. .xcref
  601.           ?begp1 <n>
  602. ?popn     = _F           ;; indicate no procedure open
  603. ?sadj     = (?sadj+1) and 0FFFEh ;; for even number of local bytes
  604.   if c                   ;; test for far procedure
  605. n         proc far       ;; begin procedure
  606.   else                   ;; near procedure
  607. n         proc near      ;; begin procedure
  608.   endif
  609.   if p                   ;; test for public procedure
  610.           public n       ;; declare public symbol
  611.   endif
  612.   ifdif <g>,<>           ;; test for no code generation
  613. ?padj     = ?sadj        ;; set parameter adjustment
  614.     if ?lclo+?prmo       ;; test for parameters or locals
  615.       if1
  616. %out _begp "&n" no code generated warning
  617.       endif
  618.     endif
  619.   else
  620.     ifidn <x>,<>         ;; test for index registers to be saved (function)
  621.       if ?sxr            ;; test for index registers to be saved (language)
  622.           push si        ;; protect si
  623.           push di        ;; protect di
  624.       endif
  625.     endif
  626.     ifdef STKCHK         ;; test for stack check on entry required
  627.           mov ax,-?lclo  ;; *  test for stack overflow
  628.           call sy__ckst  ;; *
  629.     else                 ;; no stack check required
  630.           push bp        ;; protect bp
  631.     endif
  632.     if ?sxr              ;; test for index registers saved
  633. ?sadj     = ?sadj+4      ;; correct stack adjustment
  634.     endif
  635.     if ?nglclo           ;; test for negative local offset
  636.           mov bp,sp      ;; establish stack addressability
  637.       if ?lclo           ;; test for local storage needed
  638.           sub sp,?lclo   ;; allocate local storage
  639.       endif
  640. ?padj     = ?sadj        ;; set parameter adjustment
  641.     else                 ;; positive local offset
  642.       if ?lclo           ;; test for local storage needed
  643.           sub sp,?lclo   ;; allocate local storage
  644.       endif
  645.           mov bp,sp      ;; establish stack addressability
  646. ?padj     = ?sadj+?lclo  ;; set parameter adjustment
  647.     endif
  648.   endif
  649. .cref
  650.           purge _begp    ;; erase macro
  651.           &ENDM
  652. .cref
  653.           ENDM
  654.  
  655. ; exit code
  656.  
  657. ?begp1    MACRO n        ;; define termination macro
  658. .xcref
  659. _xitp     &MACRO x
  660.   if ?nglclo             ;; test for negative local offset
  661.           mov sp,bp      ;; deallocate local variables
  662.   else                   ;; positive local offset
  663.     if ?lclo             ;; test for local storage needed
  664.           add sp,?lclo   ;; deallocate local storage
  665.     endif
  666.   endif
  667.           pop bp         ;; restore bp
  668.           pop di         ;; restore di
  669.           pop si         ;; restore si
  670.   if ?scs                ;; test for subroutine to clear stack
  671.           ret ?prmo      ;; unload stack & return
  672.   else                   ;; caller clears stack
  673.           ret            ;; return
  674.   endif
  675.           &ENDM
  676. _endp     &MACRO g,x     ;; terminate procedure
  677. .xcref
  678.   ifdif <g>,<>           ;; test for no code generation
  679.     if ?lclo+?prmo       ;; test for parameters or locals
  680.       if2
  681. %out  _begp "&n" no code generated warning
  682.       endif
  683.     endif
  684.   else
  685.           _xitp x        ;; exit procedure
  686.   endif
  687. n         endp           ;; end of procedure
  688.   if2
  689. %out end procedure &n
  690.   endif
  691. .cref
  692.           purge _endp    ;; erase macro
  693.           &ENDM
  694. .cref
  695.           ENDM
  696.  
  697. comment ~
  698. Function Arguments
  699. ~
  700.  
  701. ; parameter macros
  702.  
  703. _pb       MACRO n        ;; byte parameter
  704.           ?pd n,<byte>,2,1 ;; define byte locator
  705.           ENDM
  706.  
  707. _pw       MACRO n        ;; word parameter
  708.           ?pd n,<word>,2,2 ;; define word locator
  709.           ENDM
  710.  
  711. _pd       MACRO n        ;; double word parameter
  712.   irp x,<n>              ;; traverse name list
  713.           ?pd <&&x>,<dword>,0,4 ;; define double word locator
  714.           ?pd <?o_&&x>,<word>,2,2 ;; define offset locator
  715.           ?pd <?s_&&x>,<word>,2,2 ;; sefine segment locator
  716.   endm
  717.           ENDM
  718.  
  719. _pq       MACRO n        ;; quad word parameter
  720.           ?pd n,<qword>,8,8 ;; define quad word locator
  721.           ENDM
  722.  
  723. _pt       MACRO n        ;; ten byte parameter
  724.           ?pd n,<tbyte>,10,10 ;; define ten byte locator
  725.           ENDM
  726.  
  727. _pcp      MACRO n        ;; code pointer parameter
  728.   if SYS_C               ;; test for large code
  729.           _pd n          ;; double word pointer
  730.   else                   ;; small code
  731.           _pw n          ;; word pointer
  732.   endif
  733.           ENDM
  734.  
  735. _pdp      MACRO n        ;; data pointer parameter
  736.   if SYS_D               ;; test for large data
  737.           _pd n          ;; double word pointer
  738.   else                   ;; small data
  739.           _pw n          ;; word pointer
  740.   endif
  741.           ENDM
  742.  
  743. ; define parameter
  744.  
  745. ?pd       MACRO n,t,l,s  ;; define parameter locator
  746.   if ?popn               ;; test for procedure open
  747. .xcref
  748.     irp x,<n>            ;; traverse name list 
  749.           ?pd1 x,t,%?prmo ;; define argument locator
  750. ?prmo     = ?prmo+l      ;; update parameter offset
  751. .xcref
  752. ?t_&&x    = s            ;; set parameter size
  753.     endm
  754. .cref
  755.   else                   ;; no procedure open
  756. %out no proc open- declared parm "&n"
  757.   endif
  758.           ENDM
  759.  
  760. ?pd1      MACRO x,t,p    ;; define argument locator
  761.   ife ?fnp               ;; test for variable number of arguments (C)
  762. x         equ t ptr [bp+?padj+p] ;; define locator
  763.   else
  764. x         equ t ptr [bp+?padj+?prmo-p] ;; define locator
  765.   endif
  766.           ENDM
  767.  
  768. comment ~
  769. Local Storage
  770. ~
  771.  
  772. ; local variable macros
  773.  
  774. _lb       MACRO n        ;; local byte
  775.           ?ld n,<byte>,1,1,0 ;; define byte locator
  776.           ENDM
  777.  
  778. _lw       MACRO n        ;; local word
  779.           ?ld n,<word>,2,2,1 ;; define word locator
  780.           ENDM
  781.  
  782. _ld       MACRO n        ;; local double word
  783.   irp x,<n>              ;; scan name list
  784.           ?ld <?o_&&x>,<word>,2,2,1 ;; define offset locator
  785.           ?ld <?s_&&x>,<word>,2,2,0 ;; sefine segment locator
  786.           ?ld <&&x>,<dword>,0,4,0 ;; define double word locator
  787.   endm
  788.           ENDM
  789.  
  790. _lq       MACRO n        ;; local quad word
  791.           ?ld n,<qword>,8,8,1 ;; define quad word locator
  792.           ENDM
  793.  
  794. _lt       MACRO n        ;; local ten byte
  795.           ?ld n,<tbyte>,10,10,1 ;; define ten byte locator
  796.           ENDM
  797.  
  798. _lcp      MACRO n        ;; local code pointer
  799.   if SYS_C               ;; test for large code
  800.           _ld n          ;; double word pointer
  801.   else                   ;; small code
  802.           _lw n          ;; word pointer
  803.   endif
  804.           ENDM
  805.  
  806. _ldp      MACRO n        ;; local data pointer
  807.   if SYS_D               ;; test for large data
  808.           _ld n          ;; double word pointer
  809.   else                   ;; small data
  810.           _lw n          ;; word pointer
  811.   endif
  812.           ENDM
  813.  
  814. ; define local variable
  815.  
  816. ?ld       MACRO n,t,l,s,a ;; define local variable locator
  817.   if ?popn               ;; test for procedure open
  818. .xcref
  819. ?lclo     = ?lclo+l      ;; update local offset
  820.     if a                 ;; test for boundary alignment required
  821. ?lclo     = ((?lclo+1) and 0FFFEh) ;; force on word boundary
  822.     endif
  823.     irp x,<n>            ;; scan name list
  824.           ?ld1 x,t,%?lclo ;; define local locator
  825. .xcref ?t_&&x
  826. ?t_&&x    = s            ;; define variable type
  827.     endm
  828. .cref
  829.   else                   ;; no procedure open
  830. %out no proc open- declared local "&n"
  831.   endif
  832.           ENDM
  833.  
  834. ?ld1      MACRO x,t,o    ;; define local locator
  835.   if ?nglclo             ;; test for negative local offset
  836. x         equ t ptr [bp-o] ;; define locator
  837.   else                   ;; positive local offset
  838. x         equ t ptr [bp+o] ;; define locator
  839.   endif
  840.           ENDM
  841.  
  842. comment ~
  843. Labels
  844. ~
  845.  
  846. _lbb      MACRO n        ;; byte label
  847.           ?lb1 <&n>,1,<byte>
  848.           ENDM
  849.  
  850. _lbw      MACRO n        ;; word label
  851.           ?lb1 <&n>,2,<word>
  852.           ENDM
  853.  
  854. _lbd      MACRO n        ;; double word label
  855.           ?lb1 <&n>,4,<dword>
  856.           ENDM
  857.  
  858. _lbq      MACRO n        ;; quad word label
  859.           ?lb1 <&n>,8,<qword>
  860.           ENDM
  861.  
  862. _lbt      MACRO n        ;; ten byte label
  863.           ?lb1 <&n>,10,<tbyte>
  864.           ENDM
  865.  
  866. _lbnp     MACRO n        ;; near procedure label
  867.           ?lb1 <&n>,4,<near>
  868.           ENDM
  869.  
  870. _lbfp     MACRO n        ;; far procedure label
  871.           ?lb1 <&n>,4,<far>
  872.           ENDM
  873.  
  874. _lbp      MACRO n        ;; procedure label
  875.   if SYS_C               ;; test for large code
  876.           ?lb1 <&n>,4,<far>
  877.   else                   ;; small code
  878.           ?lb1 <&n>,2,<near>
  879.   endif
  880.           ENDM
  881.  
  882. _lbcp     MACRO n        ;; code pointer label
  883.   if SYS_C               ;; test for large code
  884.           ?lb1 <&n>,4,<dword>
  885.   else                   ;; small code
  886.           ?lb1 <&n>,2,<word>
  887.   endif
  888.           ENDM
  889.  
  890. _lbdp     MACRO n        ;; data pointer label
  891.   if SYS_D               ;; test for large data
  892.           ?lb1 <&n>,4,<dword>
  893.   else                   ;; small data
  894.           ?lb1 <&n>,2,<word>
  895.   endif
  896.           ENDM
  897.  
  898. ; define label
  899.  
  900. ?lb1      MACRO n,s,t
  901. .xcref
  902. .xcref ?pblc
  903. .cref
  904. ?pblc     = _F           ;; set private default
  905.   irp x,<n>              ;; scan name list
  906.     ifidn <public>,<&x>  ;; test for public keyword
  907. ?pblc     = _T           ;; indicate public symbol
  908.     else                 ;; not public keyword
  909.       ifidn <private>,<&x> ;; test for private keyword
  910. ?pblc     = _F           ;; indicate private symbol
  911.       else               ;; not public nor private keyword
  912. .xcref
  913. .xcref ?t_&&x
  914. ?t_&&x    = s            ;; define symbol type
  915. .cref
  916. x         label t        ;; define label
  917.         if ?pblc         ;; test for public symbol
  918.           if ?ldul       ;; test for leading underline convention
  919.           public _&&x    ;; declare symbol public
  920. _&&x      label t        ;; define public symbol
  921.           else           ;; not leading underline convention
  922.           public x       ;; declare symbol public
  923.           endif
  924.         endif
  925.       endif
  926.     endif
  927.   endm                   ;; end of name list scan
  928. .cref
  929.           ENDM
  930.  
  931. comment ~
  932. Register Control
  933. ~
  934.  
  935. ; register names
  936.  
  937. .xcref
  938. .xcref ?ah,?bh,?ch,?dh,?al,?bl,?cl,?dl,?ax,?bx,?cx,?dx
  939. .xcref ?si,?di,?sp,?bp,?cs,?ss,?ds,?es
  940. .cref
  941.  
  942. ?ah       = 1000000000000000b
  943. ?al       = 0100000000000000b
  944. ?ax       = 1100000000000000b
  945. ?bh       = 0010000000000000b
  946. ?bl       = 0001000000000000b
  947. ?bx       = 0011000000000000b
  948. ?ch       = 0000100000000000b
  949. ?cl       = 0000010000000000b
  950. ?cx       = 0000110000000000b
  951. ?dh       = 0000001000000000b
  952. ?dl       = 0000000100000000b
  953. ?dx       = 0000001100000000b
  954. ?si       = 0000000010000000b
  955. ?di       = 0000000001000000b
  956. ?sp       = 0000000000100000b
  957. ?bp       = 0000000000010000b
  958. ?cs       = 0000000000001000b
  959. ?ss       = 0000000000000100b
  960. ?ds       = 0000000000000010b
  961. ?es       = 0000000000000001b
  962.  
  963. ; define register group to save
  964.  
  965. _save     MACRO r
  966. ?rsv      = 0            ;; initialize register vector
  967.           ?save ?rsv,<r> ;; process register list
  968.           ENDM
  969.  
  970. ; define register group that is clobbered
  971.  
  972. _altr     MACRO n,r
  973. .xcref
  974. .xcref ?a_&n
  975. .cref
  976. ?a_&n     = 0            ;; initialize register vector
  977.           ?save ?a_&n,<r> ;; process register list
  978.           ENDM
  979.  
  980. ; create register vector
  981.  
  982. ?save     MACRO r,rl
  983.   irp x,<rl>             ;; scan argument list
  984.     ifdef ?&&x           ;; semitest for valid register name
  985. r         = r or ?&&x    ;; update register vector
  986.     endif
  987.   endm
  988.           ENDM
  989.  
  990. ; protect registers
  991.  
  992. ?mpush    MACRO r
  993.   irp x,<ax,bx,cx,dx,si,di,bp,sp,es,ds,ss,cs>
  994.     if r and ?&&x
  995.           push x         ;; protect register x
  996.     endif
  997.   endm
  998.           ENDM
  999.  
  1000. ; restore registers
  1001.  
  1002. ?mpop     MACRO r
  1003.   irp x,<cs,ss,ds,es,sp,bp,di,si,dx,cx,bx,ax>
  1004.     if r and ?&&x
  1005.           pop x          ;; restore register x
  1006.     endif
  1007.   endm
  1008.           ENDM
  1009.  
  1010. comment ~
  1011. Procedure Calls
  1012. ~
  1013. ; procedure call
  1014.  
  1015. _call     MACRO n,a      ;; call high level function
  1016. .xcref
  1017. .xcref ?actr
  1018. .cref
  1019.   ifnb <a>               ;; test for parameters specified
  1020.           _arg <&a>      ;; process argument list
  1021.   endif
  1022. ?argl     = 0            ;; initialize argument length
  1023.   if ?fnp                ;; fixed number of arguments
  1024. ?actr     = 0            ;; initialize argument count
  1025.   else                   ;; variable number of arguments (C protocol)
  1026. ?actr     = ?argc        ;; initialize argument count
  1027.   endif
  1028.   if ?rsv                ;; test for registers to be saved
  1029.     ifdef &a_&n          ;; test for altered registers defined
  1030. ?rsav     = ?rsv and ?a_&n ;; define registers to be saved
  1031.     else
  1032. ?rsav     = ?rsv         ;; define registers to be saved
  1033.     endif
  1034.     if ?rsav             ;; test for registers to be saved
  1035.           ?mpush ?rsav   ;; protect registers
  1036.     endif
  1037.   endif
  1038.   if ?fnp                ;; fixed number of arguments
  1039.     rept ?argc           ;; scan argument list from front
  1040. ?actr     = ?actr+1      ;; decrement argument counter
  1041.           ?call %?actr   ;; put argument on stack
  1042.     endm
  1043.   else                   ;; variable number of arguments (C protocol)
  1044.     rept ?argc           ;; scan argument list from back
  1045.           ?call %?actr   ;; put argument on stack
  1046. ?actr     = ?actr-1      ;; decrement argument counter
  1047.     endm
  1048.   endif
  1049.   if ?ldul               ;; test for leading underline convention
  1050.           call _&n       ;; call procedure
  1051.   else                   ;; no leading underline
  1052.           call n         ;; call procedure
  1053.   endif
  1054.   if ?argl               ;; test for arguments on stack
  1055.     if ?scs              ;; test for subroutine clears stack
  1056.       ifdef ?rsav        ;; test for registers to be saved
  1057.           ?mpop ?rsav    ;; restore registers
  1058.       endif
  1059.     else                 ;; caller clears stack
  1060.       if ?nglclo         ;; test for negative local offset
  1061.             add sp,?argl ;; unload stack
  1062.         ifdef ?rsav      ;; test for registers to be saved
  1063.             ?mpop ?rsav  ;; restore registers
  1064.         endif
  1065.  
  1066.       else               ;; positve local offset
  1067.         ifdef ?rsav      ;; test for registers to be saved
  1068.             add sp,?argl ;; uload stack
  1069.             ?mpop ?rsav  ;; restore registers
  1070.         else             ;; no registers to be saved
  1071.             mov sp,bp    ;; unload stack
  1072.         endif
  1073.       endif
  1074.     endif
  1075.   endif
  1076.  
  1077. ?argc     = 0            ;; reset argument count
  1078. ?argl     = 0            ;; reset argument length
  1079.           ENDM
  1080.  
  1081. ; put argument i on stack
  1082.  
  1083. ?call     MACRO i        ;; put argument on stack
  1084.           ?a_&i          ;; expand storage macro
  1085.           purge ?a_&i    ;; purge storage macro
  1086.           ENDM
  1087.  
  1088. ; determine arguments
  1089.  
  1090. _arg      MACRO a        ;; process argument list
  1091.   irp x,<&a>             ;; scan argument list
  1092. ?argc     = ?argc+1      ;; increment argument count
  1093.           ?arg1 <&x>,%?argc ;; define parameter store macro
  1094.   endm
  1095.           ENDM
  1096.  
  1097. ; define argument storing macro
  1098.  
  1099. ?arg1     MACRO n,i      ;; process argument
  1100. .xcref
  1101. .xcref ?a_&i
  1102. ?a_&i     &MACRO         ;; store argument
  1103.           ?arg2 n        ;; store argument
  1104.           &ENDM
  1105. .cref
  1106.           ENDM
  1107.  
  1108. ; store argument on stack
  1109.  
  1110. ?arg2     MACRO n        ;; store argument
  1111. ?argl     = ?argl+2      ;; increment argument length
  1112.   ifdef ?t_&n            ;; test for size defined
  1113.     ife ?t_&n            ;; test for type = 0
  1114.           push word ptr (n) ;; store word argument on stack
  1115.           EXITM          ;; exit macro
  1116.     else
  1117.     ife ?t_&n-1          ;; test for byte (type = 1)
  1118.           push word ptr (n) ;; store byte argument on stack
  1119.           EXITM          ;; exit macro
  1120.     else
  1121.     ife ?t_&n-2          ;; test for word (type = 2)
  1122.           push word ptr (n) ;; store word argument on stack
  1123.           EXITM          ;; exit macro
  1124.     else
  1125.     ife ?t_&n-4          ;; test for double word (type = 4)
  1126.           ?arg2a n       ;; store double word argument on stack
  1127.           EXITM          ;; exit macro
  1128.     else
  1129.     ife ?t_&n-8          ;; test for quad word (type = 8)
  1130.           ?arg2b n       ;; store quad word argument on stack
  1131.           EXITM          ;; exit macro
  1132.     else
  1133.     ife ?t_&n-10         ;; test for ten byte (type = 10)
  1134.           push word ptr (n)+8 ;; store least significant bytes
  1135.           ?arg2b n       ;; store quad word argument on stack
  1136.           EXITM          ;; exit macro
  1137.     endif
  1138.     endif
  1139.     endif
  1140.     endif
  1141.     endif
  1142.     endif
  1143.   else                   ;; size not defined
  1144.           push n         ;; store argument on stack
  1145.   endif
  1146.           ENDM
  1147.  
  1148. ?arg2a    MACRO n
  1149.           push word ptr (n)+2 ;; *  store double word argument on stack
  1150.           push word ptr (n) ;; *
  1151.           ENDM
  1152.  
  1153. ?arg2b    MACRO n
  1154.           push word ptr (n)+6 ;; *  store quad word argument on stack
  1155.           push word ptr (n)+4 ;; *
  1156.           arg2a n        ;; *
  1157.           ENDM
  1158.  
  1159. comment ~
  1160. end of Listing 2
  1161. ~
  1162.