I'm about to start some NT kernel mode driver development, and
realized that most of the API is done through fastcall. And it doesn't
seem like masm natively supports FASTCALL in proc/proto :(.
So, it would seem like an ideal time to write a FASTCALL macro...
As far as I know, the first three parms are to be passed in EAX,ECX,EDX,
and the following pushed to the stack. Or perhaps it's only ECX and EDX
that are used... vmm.inc seems to have some code to do this, but
it's *very* confusing :/. Some nasm macros I found at mammons
site (I think) seem to use EAX,EDX,EBX. Time to write a little C app
that uses fastcall and disassemble it, I think ;).

Ok. Here's how visual studio does it. First parameter is in ecx, next
in edx, and ther rest are pushed last-to-first on the stack. Cleanup
is done by the procedure, not the caller.
Posted on 2001-09-04 19:59:56 by f0dder
By the way, it's probably a bad idea to generate PROTOs for fastcall
functions. As I see it, the best would be to do something like the

IofCompleteRequest TEXTEQU <@IofCompleteRequest@8>
IofCompleteRequest EXTERN:DWORD

... or something similear. Any ideas? I'm currently working on a "protoizer"
that generates include files with PROTOs from vc-style import libraries.
It currently works pretty well for normal includes, and makes it
easy to use both unicode and ansi, and switch defaults, and all
sorts of good stuff :]. Now I just need to find a reasonable way to
handle them darn FASTCALLs.
Posted on 2001-09-04 20:15:21 by f0dder
There, figured out how to set up the externdef and nice alias.
Now all I need is the FASTCALL macro :D. In case anybody are
interested, I've attached the protoize executable and source code.
It's pretty ugly, but does a good job.

IofCompleteRequest TEXTEQU <@IofCompleteRequest@8>
Posted on 2001-09-04 22:14:55 by f0dder
I'll certainly take a look....
;* @ArgRev - Macro function returns a reversed order version of a

;* VARARG list.
;* Params: arglist - arguments to be reversed
@ArgRev MACRO arglist:VARARG
LOCAL txt,arg
txt TEXTEQU <>
% FOR arg,arglist
txt CATSTR <arg>, <!,>, txt

txt SUBSTR txt, 1, @SizeStr( %txt ) - 1
txt CATSTR <!<>, txt, <!>>

FASTCALL MACRO func:REQ, pp1, pp2, pp3s:VARARG
LOCAL rpp3s
IFNB <pp1>
mov ecx,pp1
IFNB <pp2>
mov edx,pp2
IFNB <pp3s>
rpp3s TEXTEQU @ArgRev(&pp3s)
FOR pp3,<rpp3s>
push pp3
call func
I haven't tested this, but it should just about get you all the way there?
Posted on 2001-09-05 19:03:07 by bitRAKE
Fastcall looks superior to stdcall, so why doesn't windows use it more often? I mean it saves at least 2 clock cycles (1 for the two pushes and 1 for the two pops)
Posted on 2001-09-06 17:15:32 by Kenny
1) windows API needs to be available to multiple languages. Fastcall
might not be easy to implement in all languages.

2) it's not always beneficial. In most APIs, saving a couple of clocks
doesn't matter at all. But fiddling registers around in your own code
could turn up annoying... imagine a loop where you need to call an
API, you suddenly have two registers you need to preserve if you
want to use them in the loop.

So, fastcall is best used for stuff where a couple of cycles actually matter.
For instance, small functions in kernel-space. Functions that are
called often.
Posted on 2001-09-06 17:31:26 by f0dder
oh... didn't think of that...

Posted on 2001-09-06 18:42:54 by Kenny