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

  1.  
  2. ;   FILENAME: IMACROS.MAC
  3. ;
  4. ;   Copyright (c) 1988 by Borland International, Inc.
  5. ;
  6. ;   DESCRIPTION: This include file implements miscellaneous useful macros.
  7. ;   The file uses ideal mode syntax.
  8. ;
  9. ;   ASSEMBLY INSTRUCTIONS: If assembling modules for 286/386 processors,
  10. ;   turn on the P286 directive 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. ;   IBIOS.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. macro   FarPtrAddress 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. macro   CompareFarPointers    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. ;   The following macro builds strings using Turbo Pascal conventions. That
  132. ;   is, the string is stored with a preceding 'length byte.' This macro is
  133. ;   an excellent example of the clever things that can be done using the
  134. ;   ORG directive.
  135. ;
  136. ;   Input
  137. ;       Id - Label to associate with the string
  138. ;       Msg - Contents of the string
  139. ;   Output
  140. ;       none
  141. ;   Calling convention
  142. ;       NA
  143. ;   Registers modified
  144. ;       none
  145.  
  146. macro   MakePascalString    Id, Msg
  147.     local   MsgLen, EndStr
  148.     ifb <Id>
  149.         display "Must pass name of string to MakePascalString"
  150.         err
  151.     else
  152.         ifb <Msg>
  153.             display "Must pass string parameter to MakePascalString
  154.             err
  155.         else
  156.             Id  db  EndStr - Id - 1, &Msg&  ; Allocate space for the string
  157.             label   EndStr  byte            ; a preceding byte storing the
  158.         endif                               ; length of the string.
  159.     endif
  160. endm
  161.  
  162.  
  163. ;   The following macro initializes bp and sp in preparation for access
  164. ;   of parameters passed to a routine on the stack. The parameter LocalVars
  165. ;   is optional and if provided indicates the amount of space that should
  166. ;   be reserved for local variables. LocalVars must be an even value.
  167. ;
  168. ;   Input
  169. ;       LocalVars - # of bytes to reserve for local variables
  170. ;   Output
  171. ;       none
  172. ;   Calling convention
  173. ;       NA
  174. ;   Registers modified
  175. ;       bp, sp
  176.  
  177. macro   InitStack   LocalVars
  178.     push    bp                  ; Set up the stack for a sub-routine
  179.     mov     bp, sp
  180.     ifnb    <LocalVars>
  181.         sub     sp, LocalVars   ; Make space for local variables
  182.     endif
  183. endm
  184.  
  185.  
  186. ;   The following macro restores bp and sp after a routine is finished
  187. ;   accessing parameters passed to a routine on the stack. The parameter
  188. ;   LocalVars is optional and if provided indicates the amount of space
  189. ;   that was reserved for local variables. LocalVars must be an even value.
  190. ;
  191. ;   Input
  192. ;       LocalVars - # of bytes that were reserved for local variables
  193. ;   Output
  194. ;       none
  195. ;   Calling convention
  196. ;       NA
  197. ;   Registers modified
  198. ;       bp, sp
  199.  
  200. macro   RestoreStack    LocalVars
  201.     ifnb    <LocalVars>
  202.         add     sp, LocalVars
  203.     endif   ; ifnb <LocalVars>
  204.     pop     bp
  205. endm    ; InitStack
  206.  
  207.  
  208. ;   The following macro returns the current segment address of video ram.
  209. ;
  210. ;   Input
  211. ;       none
  212. ;   Output
  213. ;       ax
  214. ;   Calling convention
  215. ;       NA
  216. ;   Registers modified
  217. ;       ax, bx, Flags
  218.  
  219. macro   GetVideoAddress
  220.     local   Color, Exit
  221.     GetVideoMode
  222.     cmp     al, 07h
  223.     jne     short Color
  224.     mov     ax, 0B000h      ;; It's a monochrome card
  225.     jmp     short Exit
  226. Color:
  227.     mov     ax, 0B800h      ;; It's a color card
  228. Exit:
  229. endm
  230.  
  231.  
  232.  
  233. ;   The following macro performs the Int 21h call to execute DOS's
  234. ;   services.
  235. ;
  236. ;   Input
  237. ;       Service - Service # to execute
  238. ;   Output
  239. ;       None
  240. ;   Calling convention
  241. ;       NA
  242. ;   Registers modified
  243. ;       NA
  244.  
  245. macro   DosCall Service
  246.     ifb <Service>
  247.         display "The Service parameter must be provided to DosCall
  248.         err
  249.     endif
  250.     mov ah, Service
  251.     int DOS_FUNCTION
  252. endm
  253.  
  254.  
  255. ;   The following macro loads a segment register with a value. The macro
  256. ;   attempts to do all possible checks to determine the type of the value
  257. ;   being moved into the segment register. Based on this information it
  258. ;   generates the correct code.
  259. ;
  260. ;   Input
  261. ;       Segm    - Segm register to load value into
  262. ;       Value   - Value to put on the stack
  263. ;   Output
  264. ;       none
  265. ;   Calling convention
  266. ;       NA
  267. ;   Registers modified
  268. ;       ax
  269.  
  270. macro   LoadSegment Segm, Value
  271.     local   IsSegReg
  272.  
  273.     macro   CheckRegisterName   Register
  274.         IsSegReg = 0
  275.         if (symtype Register) eq 110000b
  276.             irp Reg, <es, ds, cs, ss, fs, gs>
  277.                 ifidni  <Register>, <&Reg&>
  278.                     IsSegReg = 1                ; Return that the register
  279.                     exitm                       ; is a segment register
  280.                 endif
  281.             endm
  282.         endif
  283.     endm
  284.  
  285.     CheckRegisterName   <Value>                 ; Check if the value to be
  286.     if IsSegReg                                 ; loaded into the segment
  287.         push    Value                           ; register is itself a
  288.         pop     Segm                            ; segment register.
  289.     else
  290.         if (symtype Segm eq 24h) or (symtype Segm eq 0h)    ; Parameter is a constant
  291.             mov     ax, Value
  292.             mov     Segm, ax
  293.         else
  294.             mov     Segm, Value                 ; Value is a memory reference
  295.         endif
  296.     endif
  297. endm
  298.  
  299.  
  300.  
  301. ;   The following macro generates a beep by displaying the ASCII Bell
  302. ;   character.
  303. ;
  304. ;   Input
  305. ;       none
  306. ;   Output
  307. ;       none
  308. ;   Calling convention
  309. ;       NA
  310. ;   Registers modified
  311. ;       ax, dl
  312.  
  313. macro   Beep
  314.     mov dl, BELL
  315.     DosCall DOS_CHARACTER_OUTPUT
  316. endm
  317.  
  318.  
  319.