home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / tasm / mmacros.mac < prev    next >
Text File  |  1988-08-28  |  9KB  |  320 lines

  1.  
  2. ;   FILENAME: MMACROS.MAC
  3. ;
  4. ;   Copyright (c) 1988 by Borland International, Inc.
  5. ;
  6. ;   DESCRIPTION: This include file implements miscellaneous useful macros.
  7. ;   The file uses Masm mode syntax.
  8. ;
  9. ;   ASSEMBLY INSTRUCTIONS: If assembling modules for 286/386 processors,
  10. ;   turn the P286 directive on in order to take advantage of 286/386 specific
  11. ;   instructions. I.E.
  12. ;
  13. ;       TASM filename /jP286
  14. ;
  15. ;   NOTE: In order to use this macro file you must also include the macro file
  16. ;   MBIOS.MAC in your module.
  17. ;
  18. ;   The macros implemented in this file are:
  19. ;   Name                Function
  20. ;   ---------------     ---------------------------------------------------
  21. ;   FarPtrAddress       Calculate the absolute address of a 32-bit pointer
  22. ;   CompareFarPointers  Compare two 32-bit pointers
  23. ;   MakePascalString    Allocate a string using Turbo Pascal format
  24. ;   InitStack           Initialize the stack registers for parameter access
  25. ;   RestoreStack        Restore the stack registers
  26. ;   GetVideoAddress     Determine the segment address of video ram
  27. ;   DosCall             Performs the DOS int 21h call
  28. ;   LoadSegment         Loads a segment register with a value
  29. ;   Beep                Sounds the speaker
  30.  
  31.  
  32. ;   The following macro calculates the absolute address of the far pointer
  33. ;   passed to it.
  34. ;
  35. ;   Input
  36. ;       Segment:Ofs - Far pointer
  37. ;   Output
  38. ;       dx:ax - Absolute address of pointer(20 bits)
  39. ;   Calling convention
  40. ;       NA
  41. ;   Registers modified
  42. ;       ax, bx, cx, dx, Flags
  43.  
  44. FarPtrAddress macro Segment, Ofs
  45.     ifb <Segment>
  46.         display "Segment parameter must be provided in call to FarPtrAddress"
  47.         err
  48.     endif
  49.     ifb <Ofs>
  50.         display "Ofs parameter must be provided in call to FarPtrAddress"
  51.         err
  52.     endif
  53.  
  54.     mov     bx, Segment     ; Calculate the low 12 bits
  55.     and     bx, 0FFFh
  56.     if (@Cpu and 100b) eq 100b  ; Shift the segment value right 12 bits
  57.         shl     bx, 4       ; to prepare for addition
  58.     else
  59.         mov     cl, 4
  60.         shl     bx, cl
  61.     endif
  62.     mov     dx, Segment
  63.     if (@Cpu and 100b) eq 100b  ; Shift the segment value right 12  bits
  64.         shr     dx, 12      ; to prepare for addition
  65.     else
  66.         mov     cl, 12
  67.         shr     dx, cl
  68.     endif
  69.     mov     ax, Ofs         ; Determine the low 16 bits of the 20-bit
  70.     add     ax, bx          ; address
  71.     adc     dx, 0           ; Calculate the absolute segment
  72. endm
  73.  
  74.  
  75. ;   The following macros compares two far pointers to determine their
  76. ;   relative absolute addresses.
  77. ;
  78. ;   Input
  79. ;       Seg1:Ofs1 - Far pointer
  80. ;       Seg2:Ofs2 - Far pointer
  81. ;   Output
  82. ;       The Flags register is set by the CMP instruction.
  83. ;   Calling convention
  84. ;       NA
  85. ;   Registers modified
  86. ;       ax, bx, cx, dx, Flags
  87.  
  88. CompareFarPointers    macro Seg1, Ofs1, Seg2, Ofs2
  89.     local   Exit, SegmentsEqual
  90.     ifb <Seg1>
  91.         display "Need to declare Seg1 in call to CompareFarPointers"
  92.         err
  93.     endif
  94.     ifb <Seg2>
  95.         display "Need to declare Seg2 in call to CompareFarPointers"
  96.         err
  97.     endif
  98.     ifb <Ofs1>
  99.         display "Need to declare Ofs1 in call to CompareFarPointers"
  100.         err
  101.     endif
  102.     ifb <Ofs2>
  103.         display "Need to declare Ofs2 in call to CompareFarPointers"
  104.         err
  105.     endif
  106.  
  107.     mov     ax, Seg1            ; Load segment registers
  108.     mov     dx, Seg2
  109.     cmp     ax, dx              ; Check if segment registers are equal
  110.     je      short SegmentsEqual
  111.  
  112.     ; If the segments aren't equal we have to calculate the absolute
  113.     ; addresses of the pointers
  114.  
  115.     FarPtrAddress Seg1, Ofs1    ; Calculate absolute adress of Seg1:Ofs1
  116.     push    dx                  ; Store calculated values on the stack
  117.     push    ax
  118.     FarPtrAddress Seg2, Ofs2    ; Calculate absolute adress of Seg2:Ofs2
  119.     mov     bx, sp
  120.     cmp     [ss:bx+2], dx       ; Compare absolute segment adresses
  121.     pop     bx                  ; Clean up the stack
  122.     pop     bx
  123.     jne     short Exit          ; If they aren't equal we're done
  124.     cmp     [ss:bx], ax         ; Check absolute offsets
  125.     jmp     short Exit
  126. SegmentsEqual:
  127.     cmp     Ofs1, Ofs2          ; Compare offsets
  128. Exit:
  129. endm
  130.  
  131.  
  132. ;   The following macro builds strings using Turbo Pascal conventions. That
  133. ;   is, the string is stored with a preceding 'length byte.' This macro is
  134. ;   an excellent example of the clever things that can be done using the
  135. ;   ORG directive.
  136. ;
  137. ;   Input
  138. ;       Id - Label to associate with the string
  139. ;       Msg - Contents of the string
  140. ;   Output
  141. ;       none
  142. ;   Calling convention
  143. ;       NA
  144. ;   Registers modified
  145. ;       none
  146.  
  147. MakePascalString    macro   Id, Msg
  148.     local   MsgLen, EndStr
  149.     ifb <Id>
  150.         display "Must pass name of string to MakePascalString"
  151.         err
  152.     else
  153.         ifb <Msg>
  154.             display "Must pass string parameter to MakePascalString
  155.             err
  156.         else
  157.             Id  db  EndStr - Id - 1, "&Msg&"    ; Allocate space for the string
  158.             label   EndStr  byte                ; a preceding byte storing the
  159.         endif                                   ; length of the string.
  160.     endif
  161. endm
  162.  
  163.  
  164. ;   The following macro initializes bp and sp in preparation for access
  165. ;   of parameters passed to a routine on the stack. The parameter LocalVars
  166. ;   is optional and if provided indicates the amount of space that should
  167. ;   be reserved for local variables. LocalVars must be an even value.
  168. ;
  169. ;   Input
  170. ;       LocalVars - # of bytes to reserve for local variables
  171. ;   Output
  172. ;       none
  173. ;   Calling convention
  174. ;       NA
  175. ;   Registers modified
  176. ;       bp, sp
  177.  
  178. InitStack   macro   LocalVars
  179.     push    bp                  ; Set up the stack for a sub-routine
  180.     mov     bp, sp
  181.     ifnb    <LocalVars>
  182.         sub     sp, LocalVars   ; Make space for local variables
  183.     endif
  184. endm
  185.  
  186.  
  187. ;   The following macro restores bp and sp after a routine is finished
  188. ;   accessing parameters passed to a routine on the stack. The parameter
  189. ;   LocalVars is optional and if provided indicates the amount of space
  190. ;   that was reserved for local variables. LocalVars must be an even value.
  191. ;
  192. ;   Input
  193. ;       LocalVars - # of bytes that were reserved for local variables
  194. ;   Output
  195. ;       none
  196. ;   Calling convention
  197. ;       NA
  198. ;   Registers modified
  199. ;       bp, sp
  200.  
  201. RestoreStack    macro   LocalVars
  202.     ifnb    <LocalVars>
  203.         add     sp, LocalVars
  204.     endif
  205.     pop     bp
  206. endm
  207.  
  208.  
  209. ;   The following macro returns the current segment address of video ram.
  210. ;
  211. ;   Input
  212. ;       none
  213. ;   Output
  214. ;       ax
  215. ;   Calling convention
  216. ;       NA
  217. ;   Registers modified
  218. ;       ax, bx, Flags
  219.  
  220. GetVideoAddress macro
  221.     local   Color, Exit
  222.     GetVideoMode
  223.     cmp     al, 07h
  224.     jne     short Color
  225.     mov     ax, 0B000h      ;; It's a monochrome card
  226.     jmp     short Exit
  227. Color:
  228.     mov     ax, 0B800h      ;; It's a color card
  229. Exit:
  230. endm
  231.  
  232.  
  233.  
  234. ;   The following macro performs the Int 21h call to execute DOS's
  235. ;   services.
  236. ;
  237. ;   Input
  238. ;       Service - Service # to execute
  239. ;   Output
  240. ;       None
  241. ;   Calling convention
  242. ;       NA
  243. ;   Registers modified
  244. ;       NA
  245.  
  246. DosCall macro   Service
  247.     ifb <Service>
  248.         display "The Service parameter must be provided to DosCall
  249.         err
  250.     endif
  251.     mov ah, Service
  252.     int DOS_FUNCTION
  253. endm
  254.  
  255.  
  256. ;   The following macro loads a segment register with a value. The macro
  257. ;   attempts to do all possible checks to determine the type of the value
  258. ;   being moved into the segment register. Based on this information it
  259. ;   generates the correct code.
  260. ;
  261. ;   Input
  262. ;       Segm    - Segm register to load value into
  263. ;       Value   - Value to put on the stack
  264. ;   Output
  265. ;       none
  266. ;   Calling convention
  267. ;       NA
  268. ;   Registers modified
  269. ;       ax
  270.  
  271. LoadSegment macro   Segm, Value
  272.     local   IsSegReg
  273.  
  274.     CheckRegisterName   macro   Register
  275.         IsSegReg = 0
  276.         if (symtype Register) eq 110000b
  277.             irp Reg, <es, ds, cs, ss, fs, gs>
  278.                 ifidni  <Register>, <&Reg&>
  279.                     IsSegReg = 1                ; Return that the register
  280.                     exitm                       ; is a segment register
  281.                 endif
  282.             endm
  283.         endif
  284.     endm
  285.  
  286.     CheckRegisterName   <Value>                 ; Check if the value to be
  287.     if IsSegReg                                 ; loaded into the segment
  288.         push    Value                           ; register is itself a
  289.         pop     Segm                            ; segment register.
  290.     else
  291.         if (symtype Segm eq 24h) or (symtype Segm eq 0h)    ; Parameter is a constant
  292.             mov     ax, Value
  293.             mov     Segm, ax
  294.         else
  295.             mov     Segm, Value                 ; Value is a memory reference
  296.         endif
  297.     endif
  298. endm
  299.  
  300.  
  301.  
  302. ;   The following macro generates a beep by displaying the ASCII Bell
  303. ;   character.
  304. ;
  305. ;   Input
  306. ;       none
  307. ;   Output
  308. ;       none
  309. ;   Calling convention
  310. ;       NA
  311. ;   Registers modified
  312. ;       ax, dl
  313.  
  314. Beep    macro
  315.     mov dl, BELL
  316.     DosCall DOS_CHARACTER_OUTPUT
  317. endm
  318.  
  319.  
  320.