1 ; THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
\r
2 ; SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
\r
3 ; END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
\r
4 ; ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
\r
5 ; IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
\r
6 ; SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
\r
7 ; FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
\r
8 ; CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
\r
9 ; AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
\r
10 ; COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
\r
11 ;Shortcuts for casting
\r
17 ;The macros @ArgCount() & @ArgRev() are from the file MACROS.INC, provided
\r
18 ;with MASM. I have included them here because MACROS.INC has bugs, so I
\r
19 ;couldn't just include it.
\r
21 ; Utility Macros - Version 1.0 - for Microsoft Macro Assembler 6.0
\r
22 ; (C) Copyright Microsoft Corporation, 1987,1988,1989,1990
\r
24 ;* @ArgCount - Macro function returns the number of arguments in a
\r
27 ;* Params: arglist - arguments to be counted
\r
29 @ArgCount MACRO arglist:VARARG
\r
38 ;* @ArgRev - Macro function returns a reversed order version of a
\r
41 ;* Shows: Operators - <> ! %
\r
42 ;* String directive - SUBSTR
\r
43 ;* Predefined function - @SizeStr
\r
45 ;* Params: arglist - arguments to be reversed
\r
47 @ArgRev MACRO arglist:vararg
\r
50 % FOR arg, <arglist>
\r
51 txt CATSTR <arg>, <!,>, txt
\r
54 txt SUBSTR txt, 1, @SizeStr( %txt ) - 1
\r
55 txt CATSTR <!<>, txt, <!>>
\r
59 ;These macros are used for decalaring external vars and functions
\r
61 ;this macro is used to declare several symbols of the same type
\r
62 ;usage is: extdef type,sym0,sym1,...
\r
63 extdef macro type,syms:vararg
\r
69 ;this macro is used to generate ext<type> macros
\r
70 extgen macro type,id
\r
71 ext&id macro syms:vararg
\r
76 ;macros for common types, such as word (extw), byte (extb), & near (extn)
\r
84 ;compute the absolute value of eax. afterwards, edx=sign (0 or -1)
\r
91 ;PUSHM & POPM are used for multiple registers. Note that POPM pops in the
\r
92 ;reverse order from PUSHM, so the list of regs shouls be the same for both.
\r
93 ;You can also define a constant which is a register list, and use it as the
\r
94 ;argument to both macros.
\r
96 ;push multiple registers
\r
97 pushm macro args:vararg
\r
104 ;pop multiple registers
\r
105 popm macro args:vararg
\r
107 % for arg,@ArgRev(args)
\r
112 ;PUSHLONG pushes a long, zero extending the argument if necessary
\r
113 ;it trashes no registers
\r
117 if s EQ 0 ;constant, I think
\r
129 ;PUSHML is pushm using pushlong
\r
130 pushml macro args:vararg
\r
138 ;DBSTR stores a string with occurances of \n converted to newlines
\r
139 ;this macro expects quotes around the string
\r
141 ;note the 'fudge' variable. This fixes an odd problem with the way
\r
142 ;the string macros deal with backslashes - @InStr() treats them like
\r
143 ;any other character, but @SubStr() ignores them
\r
145 local pos,oldpos,len,fudge
\r
147 oldpos = 2 ;skip initial quote
\r
149 len = @SizeStr(str)
\r
151 pos = @InStr(oldpos,str,<\n>)
\r
153 while pos GE oldpos
\r
156 %db '&@SubStr(<&str>,&oldpos-&fudge,&pos-&oldpos)'
\r
162 pos = @InStr(oldpos,<str>,<\n>)
\r
167 ;;; %db '&@SubStr(&str,&oldpos-&fudge,&len-&oldpos-1)'
\r
168 %db '&@SubStr(&str,&oldpos-&fudge,&len-&oldpos)'
\r
174 ;MPRINTF is a macro interface to the mprintf funcion. It puts the format
\r
175 ;string in the code segment at the current location, pushes the args, and
\r
176 ;calls mprintf. If window is not specified, zero is assumed
\r
177 mprintf macro window:=<0>,format:req,args:vararg
\r
188 % pushml @ArgRev(args)
\r
190 pushml offset string,window
\r
192 add esp,(@ArgCount(args)+2)*4 ;fix stack
\r
198 ;MPRINTF_AT - version of mprintf with coordinates
\r
199 mprintf_at macro window:=<0>,row,col,format:req,args:vararg
\r
210 % pushml @ArgRev(args)
\r
212 pushml offset string,col,row,window
\r
214 add esp,(@ArgCount(args)+4)*4 ;fix stack
\r
220 ;DEBUG calls mprintf with window 0, preserving all registers and flags
\r
221 ;is is conditionall assembled based on the DEBUG_ON flags
\r
222 debug macro format:req,args:vararg
\r
225 push eax ;mprintf trashes eax
\r
226 mprintf ,format,args
\r
232 ;DEBUG_AT - version of debug with coordinates
\r
233 debug_at macro row,col,format:req,args:vararg
\r
236 push eax ;mprintf trashes eax
\r
237 mprintf_at ,row,col,format,args
\r
243 ;Debugging breakpoint macros
\r
245 ;print a message, and do an int3 to pop into the debugger
\r
246 debug_brk macro str
\r
253 break_if macro cc,str
\r
254 local skip,yes_break
\r
258 yes_break: debug_brk str
\r
263 ;returns the bit number of the highest bit
\r
279 ;returns the bit number of the lowest bit
\r
288 while (t and 1) EQ 0
\r
297 ;"multiply" the given register by a constant, using whatever method is
\r
298 ;best for the given constant
\r
306 lea reg,[reg*2+reg]
\r
308 lea reg,[reg*4+reg]
\r
310 lea reg,[reg*2+reg] ;*3
\r
313 lea reg,[reg*8+reg]
\r
315 lea reg,[reg*8+reg]
\r
324 echo Warning: Using imul, to perform multiply by &c
\r