PSMACROS.INC 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. ;THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  2. ;SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
  3. ;END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  4. ;ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  5. ;IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  6. ;SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  7. ;FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  8. ;CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
  9. ;AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
  10. ;COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
  11. ;
  12. ; $Source: f:/miner/source/includes/rcs/psmacros.inc $
  13. ; $Revision: 1.12 $
  14. ; $Author: matt $
  15. ; $Date: 1994/12/06 14:32:19 $
  16. ;
  17. ; Useful macros. Everyone should use these.
  18. ;
  19. ; $Log: psmacros.inc $
  20. ; Revision 1.12 1994/12/06 14:32:19 matt
  21. ; Made mprintf turn off if NMONO set
  22. ;
  23. ; Revision 1.11 1994/11/27 23:18:19 matt
  24. ; Made mprintf go away when debugging turned off
  25. ;
  26. ; Revision 1.10 1994/03/25 18:00:34 matt
  27. ; Added imulc of 6
  28. ;
  29. ; Revision 1.9 1994/02/10 18:00:58 matt
  30. ; Changed 'if DEBUG_ON' to 'ifndef NDEBUG'
  31. ;
  32. ; Revision 1.8 1993/11/22 23:47:06 matt
  33. ; debug macros were trashing eax
  34. ;
  35. ; Revision 1.7 1993/11/04 12:39:25 mike
  36. ; Modify imulc macro to support fast multiply by 36
  37. ; and multiply anything using imul, but give warning.
  38. ;
  39. ; Revision 1.6 1993/10/19 21:17:31 matt
  40. ; Added abs_eax macro
  41. ;
  42. ; Revision 1.5 1993/09/26 22:28:21 matt
  43. ; Removed extra register pushes in mprintf
  44. ; Make DEBUG_ON all uppercase since we seem to have case sensitivity on
  45. ;
  46. ; Revision 1.4 1993/09/26 19:22:30 matt
  47. ; Added imulc macro, to multiply a register by a constant. It does not
  48. ; at this time support arbitrary constants, only 0,1,3,5,9, and powers of 2
  49. ;
  50. ; Revision 1.3 1993/09/13 11:50:57 matt
  51. ; Added 'b' & 'w', aliases for 'byte ptr' and 'word ptr'
  52. ;
  53. ; Revision 1.2 1993/09/03 19:00:03 matt
  54. ; Added breakpoint macros
  55. ;
  56. ; Revision 1.1 1993/08/24 12:51:52 matt
  57. ; Initial revision
  58. ;
  59. ;
  60. ;
  61. ;Shortcuts for casting
  62. w equ word ptr
  63. b equ byte ptr
  64. ;The macros @ArgCount() & @ArgRev() are from the file MACROS.INC, provided
  65. ;with MASM. I have included them here because MACROS.INC has bugs, so I
  66. ;couldn't just include it.
  67. ; Utility Macros - Version 1.0 - for Microsoft Macro Assembler 6.0
  68. ; (C) Copyright Microsoft Corporation, 1987,1988,1989,1990
  69. ;* @ArgCount - Macro function returns the number of arguments in a
  70. ;* VARARG list.
  71. ;*
  72. ;* Params: arglist - arguments to be counted
  73. @ArgCount MACRO arglist:VARARG
  74. LOCAL count
  75. count = 0
  76. FOR arg, <arglist>
  77. count = count + 1
  78. ENDM
  79. EXITM %count
  80. ENDM
  81. ;* @ArgRev - Macro function returns a reversed order version of a
  82. ;* VARARG list.
  83. ;*
  84. ;* Shows: Operators - <> ! %
  85. ;* String directive - SUBSTR
  86. ;* Predefined function - @SizeStr
  87. ;*
  88. ;* Params: arglist - arguments to be reversed
  89. @ArgRev MACRO arglist:vararg
  90. LOCAL txt, arg
  91. txt TEXTEQU <>
  92. % FOR arg, <arglist>
  93. txt CATSTR <arg>, <!,>, txt
  94. ENDM
  95. txt SUBSTR txt, 1, @SizeStr( %txt ) - 1
  96. txt CATSTR <!<>, txt, <!>>
  97. EXITM txt
  98. ENDM
  99. ;These macros are used for decalaring external vars and functions
  100. ;this macro is used to declare several symbols of the same type
  101. ;usage is: extdef type,sym0,sym1,...
  102. extdef macro type,syms:vararg
  103. for sym,<syms>
  104. externdef sym:type
  105. endm
  106. endm
  107. ;this macro is used to generate ext<type> macros
  108. extgen macro type,id
  109. ext&id macro syms:vararg
  110. extdef type,syms
  111. endm
  112. endm
  113. ;macros for common types, such as word (extw), byte (extb), & near (extn)
  114. extgen word,w
  115. extgen byte,b
  116. extgen dword,d
  117. extgen near,n
  118. ;compute the absolute value of eax. afterwards, edx=sign (0 or -1)
  119. abs_eax macro
  120. cdq
  121. xor eax,edx
  122. sub eax,edx
  123. endm
  124. ;PUSHM & POPM are used for multiple registers. Note that POPM pops in the
  125. ;reverse order from PUSHM, so the list of regs shouls be the same for both.
  126. ;You can also define a constant which is a register list, and use it as the
  127. ;argument to both macros.
  128. ;push multiple registers
  129. pushm macro args:vararg
  130. local arg
  131. for arg,<args>
  132. push arg
  133. endm
  134. endm
  135. ;pop multiple registers
  136. popm macro args:vararg
  137. local arg
  138. % for arg,@ArgRev(args)
  139. pop arg
  140. endm
  141. endm
  142. ;PUSHLONG pushes a long, zero extending the argument if necessary
  143. ;it trashes no registers
  144. pushlong macro arg
  145. local s
  146. s = TYPE arg
  147. if s EQ 0 ;constant, I think
  148. push arg
  149. elseif s LT 4
  150. push eax
  151. movzx eax,arg
  152. xchg eax,[esp]
  153. else
  154. push arg
  155. endif
  156. endm
  157. ;PUSHML is pushm using pushlong
  158. pushml macro args:vararg
  159. local arg
  160. for arg,<args>
  161. pushlong arg
  162. endm
  163. endm
  164. ;DBSTR stores a string with occurances of \n converted to newlines
  165. ;this macro expects quotes around the string
  166. ;
  167. ;note the 'fudge' variable. This fixes an odd problem with the way
  168. ;the string macros deal with backslashes - @InStr() treats them like
  169. ;any other character, but @SubStr() ignores them
  170. dbstr macro str
  171. local pos,oldpos,len,fudge
  172. oldpos = 2 ;skip initial quote
  173. fudge = 0
  174. len = @SizeStr(str)
  175. pos = @InStr(oldpos,str,<\n>)
  176. while pos GE oldpos
  177. if pos GT oldpos
  178. %db '&@SubStr(<&str>,&oldpos-&fudge,&pos-&oldpos)'
  179. endif
  180. db 10
  181. oldpos = pos+2
  182. fudge = fudge+1
  183. pos = @InStr(oldpos,<str>,<\n>)
  184. endm
  185. if oldpos LT len
  186. ;;; %db '&@SubStr(&str,&oldpos-&fudge,&len-&oldpos-1)'
  187. %db '&@SubStr(&str,&oldpos-&fudge,&len-&oldpos)'
  188. endif
  189. endm
  190. ;MPRINTF is a macro interface to the mprintf funcion. It puts the format
  191. ;string in the code segment at the current location, pushes the args, and
  192. ;calls mprintf. If window is not specified, zero is assumed
  193. mprintf macro window:=<0>,format:req,args:vararg
  194. local string,skip
  195. ifndef NDEBUG
  196. ifndef NMONO
  197. extn _mprintf_
  198. jmp skip
  199. string label byte
  200. dbstr format
  201. db 0
  202. skip:
  203. ifnb <args>
  204. % pushml @ArgRev(args)
  205. endif
  206. pushml offset string,window
  207. call _mprintf_
  208. add esp,(@ArgCount(args)+2)*4 ;fix stack
  209. endif
  210. endif
  211. endm
  212. ;MPRINTF_AT - version of mprintf with coordinates
  213. mprintf_at macro window:=<0>,row,col,format:req,args:vararg
  214. local string,skip
  215. ifndef NDEBUG
  216. ifndef NMONO
  217. extn _mprintf_at_
  218. jmp skip
  219. string label byte
  220. dbstr format
  221. db 0
  222. skip:
  223. ifnb <args>
  224. % pushml @ArgRev(args)
  225. endif
  226. pushml offset string,col,row,window
  227. call _mprintf_at_
  228. add esp,(@ArgCount(args)+4)*4 ;fix stack
  229. endif
  230. endif
  231. endm
  232. ;DEBUG calls mprintf with window 0, preserving all registers and flags
  233. ;is is conditionall assembled based on the DEBUG_ON flags
  234. debug macro format:req,args:vararg
  235. ifndef NDEBUG
  236. pushf ;save flags
  237. push eax ;mprintf trashes eax
  238. mprintf ,format,args
  239. pop eax
  240. popf
  241. endif
  242. endm
  243. ;DEBUG_AT - version of debug with coordinates
  244. debug_at macro row,col,format:req,args:vararg
  245. ifndef NDEBUG
  246. pushf ;save flags
  247. push eax ;mprintf trashes eax
  248. mprintf_at ,row,col,format,args
  249. pop eax
  250. popf
  251. endif
  252. endm
  253. ;Debugging breakpoint macros
  254. ;print a message, and do an int3 to pop into the debugger
  255. debug_brk macro str
  256. ifndef NDEBUG
  257. debug str
  258. int 3
  259. endif
  260. endm
  261. break_if macro cc,str
  262. local skip,yes_break
  263. ifndef NDEBUG
  264. j&cc yes_break
  265. jmp skip
  266. yes_break: debug_brk str
  267. skip:
  268. endif
  269. endm
  270. ;returns the bit number of the highest bit
  271. @HighBit macro n
  272. local t,c
  273. if n EQ 0
  274. exitm <-1> ;error!
  275. else
  276. t = n
  277. c = 0
  278. while t GT 1
  279. t = t SHR 1
  280. c = c+1
  281. endm
  282. exitm <c>
  283. endif
  284. endm
  285. ;returns the bit number of the lowest bit
  286. @LowBit macro n
  287. ;local t,c
  288. local c
  289. if n EQ 0
  290. exitm <-1> ;error!
  291. else
  292. t = n
  293. c = 0
  294. while (t and 1) EQ 0
  295. t = t SHR 1
  296. c = c+1
  297. endm
  298. exitm <c>
  299. endif
  300. endm
  301. ;"multiply" the given register by a constant, using whatever method is
  302. ;best for the given constant
  303. imulc macro reg,c
  304. local low,high
  305. if c EQ 0
  306. xor reg,reg
  307. elseif c EQ 1
  308. elseif c EQ 3
  309. lea reg,[reg*2+reg]
  310. elseif c EQ 5
  311. lea reg,[reg*4+reg]
  312. elseif c EQ 6
  313. lea reg,[reg*2+reg] ;*3
  314. shl reg,1 ;*6
  315. elseif c EQ 9
  316. lea reg,[reg*8+reg]
  317. elseif c EQ 36
  318. lea reg,[reg*8+reg]
  319. sal reg,2
  320. else
  321. low = @LowBit(c)
  322. high = @HighBit(c)
  323. if low EQ high
  324. shl reg,@LowBit(c)
  325. else
  326. imul reg,c
  327. echo Warning: Using imul, to perform multiply by &c
  328. ;; .err
  329. endif
  330. endif
  331. endm