News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Timings macro

Started by jj2007, April 19, 2009, 10:48:34 AM

Previous topic - Next topic

jj2007

After seeing too many complicated constructs to get cycles displayed, here a way to automate the process a little bit. Note it won't work with those who want to squeeze out the last cycles by passing parameters in registers.

Usage:
timings InString, 1, addr MainString, addr SubString

Output:
512     InString, 1, addr MainString, addr SubString
514     InString, 1, addr MainString, addr SubString
512     InString, 1, addr MainString, addr SubString
513     InString, 1, addr MainString, addr SubString
515     InString, 1, addr MainString, addr SubString

Average cycle count:    513



timings MACRO algo, a1, a2, a3, a4, a5, a6
LOCAL tmp$, out$, Description
  ifndef LOOP_COUNT
LOOP_COUNT = 1000000 ;; default: one Million
  endif
  ifndef CurAlgo
  CurAlgo equ <>
  endif
  ifdif CurAlgo, <algo>
  CurAlgo equ <algo>
  endif
  Description equ CurAlgo

  tmp$ CATSTR <invoke >, <algo>
  ifnb <a1>
tmp$ CATSTR tmp$, <, >, <a1>
Description CATSTR Description, <, >, <a1>
  ifnb <a2>
tmp$ CATSTR tmp$, <, >, <a2>
Description CATSTR Description, <, >, <a2>
  ifnb <a3>
tmp$ CATSTR tmp$, <, >, <a3>
Description CATSTR Description, <, >, <a3>
  ifnb <a4>
tmp$ CATSTR tmp$, <, >, <a4>
Description CATSTR Description, <, >, <a4>
  ifnb <a5>
tmp$ CATSTR tmp$, <, >, <a5>
Description CATSTR Description, <, >, <a5>
  endif
  endif
  endif
  endif
  endif
  ifndef globcycles ;; we might need to calculate a global average count
  .data?
  globcycles dd ?
  globcount dd ?
  .code
  endif
  ifndef REP_CT
REP_CT = 1
  endif
  ifndef REP_CTold
REP_CTold = REP_CT
  endif
  if REP_CT gt 1
  if REP_CTold eq 1
print chr$(13, 10)
endif
REP_CTold = REP_CT
  endif
  ;% echo tmp$ ;; uncomment to see what exactly you are invoking
  REPEAT REP_CT
invoke Sleep, 50
counter_begin LOOP_COUNT, HIGH_PRIORITY_CLASS
tmp$
counter_end
add globcycles, eax
inc globcount
out$ CATSTR <print str$(eax), 9, ">, Description, <", 13, 10>
out$
  ENDM
  if REP_CT gt 1
print chr$(13, 10)
  endif
ENDM

NightWare

Quote from: jj2007 on April 19, 2009, 10:48:34 AM
Note it won't work with those who want to squeeze out the last cycles by passing parameters in registers.
:P then i officially hate you.

mitchi

Do you have a more complete source code example jj?
I don't really get it just from looking at this.

jj2007

Quote from: NightWare on April 20, 2009, 02:34:11 AM
Quote from: jj2007 on April 19, 2009, 10:48:34 AM
Note it won't work with those who want to squeeze out the last cycles by passing parameters in registers.
:P then i officially hate you.

Make love not war :thumbu

262     DemoFastCall, ecx:82, edx:offset MainString, addr SubString
514     InString, 1, addr MainString, addr SubString

Usage:
timings InString, 1, addr MainString, addr SubString
timings DemoFastCall, ecx:82, edx:offset MainString, addr SubString   ; the FASTCALL variant

DemoFastCall proc arg3:DWORD
invoke InString, ecx, edx, arg3
ret
DemoFastCall endp

[attachment deleted by admin]

MichaelW

#4
Instead of Microsoft fastcall, why not do something like Borland fastcall and pass the first three parameters in EAX, EDX, and ECX? For procedures that return in EAX or EDX:EAX, passing the parameters in EAX or EDX:EAX can help minimize the number of instructions.
eschew obfuscation

jj2007

Quote from: MichaelW on April 21, 2009, 01:05:42 AM
Instead of Microsoft fastcall, why not do something like Borland fastcall and pass the first three parameters in EAX, EDX, and ECX? For procedures that return in EAX or EDX:EAX, passing the parameters in EAX or EDX:EAX can help minimize the number of instructions.

Michael,

Originally, I only wanted to simplify your TIMER routines, but since there seems to be interest in fastcall, I have modified it now:

FcDemo3Regs   PROTO      ; the procedure has 3 arguments, all three are passed through registers
fcinv FcDemo3Regs, ecx:82, edx:offset MainString, eax:offset SubString

FcDemo2Regs   PROTO: DWORD   ; the procedure has 3 arguments, one is passed on the stack
fcinv FcDemo2Regs, ecx:82, edx:offset MainString, offset SubString

; same for obtaining cycle counts in a standardised format:
timings FcDemo2Regs, ecx:82, edx:offset MainString, offset SubString

Note that the eax:xxx syntax expects offset Mystring, not addr Mystring.

In the examples, I chose the order ecx/edx/eax, but the macros accept any order.

[attachment deleted by admin]

jj2007

Here is the final (?) version of the fastcall macros. What's new?

- accepts fcinv FcDemo2Regs, ecx:99, edx:addr SourceString, addr SubString and translates it to lea edx, SourceString if (and only if) SourceString is a local variable

- just for fun, I added a help feature: fcinv ? will stop assembly and display this message somewhere in your IDE's output window:

___________________________________

*** How to use the fcinv macro: ***
fcinv FcDemo2Regs, ecx:82, edx:offset MainString, addr SubString
you can use up to 3 registers in whatever order you like
the PROTO must take care only of those arguments that you pass over the stack
___________________________________

.nolist
include \masm32\include\masm32rt.inc
.686
.xmm
include \masm32\macros\timers.asm
include \masm32\macros\fcinvoke.asm

; Usage:

FcDemo3Regs PROTO ; the procedure has 3 arguments, all three are passed through registers
; fcinv FcDemo3Regs, ecx:82, edx:offset MainString, eax:offset SubString

FcDemo2Regs PROTO: DWORD ; the procedure has 3 arguments, only one is passed on the stack
; fcinv FcDemo2Regs, ecx:82, edx:offset MainString, offset SubString

; same for obtaining timings in a standardised format:
; showcycles FcDemo2Regs, ecx:82, edx:offset MainString, offset SubString

.code
SourceString db "This is a long string meant for testing the Masm32 lib InString algo, and we want to find the word 'end'", 0
SubString db "end", 0

start:
if 0 ; put 1 to test the help feature
fcinv ? ; get help on
showcycles ? ; these macros
else

print "The InString results are "
fcinv FcDemo2Regs, ecx:99, edx:addr SourceString, addr SubString
print str$(eax), "/"
fcinv FcDemo3Regs, ecx:50, edx:offset SourceString, eax:offset SubString
print str$(eax), "/"
fcinv FcDemo2Regs, ecx:1, edx:chr$("Does this string have an end?"), offset SubString
print str$(eax), 13, 10, 10

showcycles FcDemo3Regs, ecx:99, edx:offset SourceString, eax:addr SubString
showcycles FcDemo2Regs, ecx:50, edx:addr SourceString, offset SubString
showcycles FcDemo2Regs, ecx:01, edx:addr SourceString, addr SubString
showcycles FcDemo2Regs, ecx:25, edx:chr$("Does this string have an end?"), offset SubString

and globcycles, 0 ; reset the average cycles
and globcount, 0 ; and the counter

REP_CT = 5 ; optional: perform the showcycles for five lines, to see the variance
showcycles InString, 1, addr SourceString, addr SubString ; --------- with the timings macro: one line ---------

print chr$("Average cycle count for last 5:" , 9)
mov eax, globcycles
cdq
div globcount
print str$(eax), 13, 10, 10
inkey "--- ok ---"
exit

endif

FcDemo2Regs proc arg3:DWORD
invoke InString, ecx, edx, arg3
ret
FcDemo2Regs endp

FcDemo3Regs proc
invoke InString, ecx, edx, eax
ret
FcDemo3Regs endp

end start


To use these macros, extract all files to a temporary folder on the same drive as Masm32, then start InstallFastCall.bat
The latter will copy two files to their destinations:
\masm32\macros\fcinvoke.asm
\masm32\macros\macrohlp.inc

[attachment deleted by admin]