without worrying about esp clobber?
Sure, as long as you remember that esp was modified. For example, if "y"
is defined as an offset from [ebp], then no problem. But if it is defined
as an offset from [esp], then you need to remember that esp has changed.
On the other hand, there's no real advantage to deferring the adjustment.
This kind of thing is the reason that calling conventions in x86 often use
a "callee cleans up" standard (using the "ret 4" instruction) instead of
"caller cleans up".
--
Tim Roberts, ti...@probo.com
Providenza & Boekelheide, Inc.
"callee cleans up" might look nice, but what about routines that take a
variable (unspecified) number/type of params? Think `c` printf()
Only the caller knows for sure how many params were pushed.
The callee could guess from the fmt string, but any error will return the
wrong ESP. With stack frames, in many cases this will pass unnoticed,
but could give some hard-to-track errors.
-- Robert
>"callee cleans up" might look nice, but what about routines that take a
>variable (unspecified) number/type of params? Think `c` printf()
>Only the caller knows for sure how many params were pushed.
Either pass the length of the parms pushed, or pass a pointer to a
list of the parms. More work, but either would work.
>The callee could guess from the fmt string, but any error will return the
>wrong ESP. With stack frames, in many cases this will pass unnoticed,
>but could give some hard-to-track errors.
True -- bad idea. :-)
--
ArarghMail909 at [drop the 'http://www.' from ->] http://www.arargh.com
BCET Basic Compiler Page: http://www.arargh.com/basic/index.html
To reply by email, remove the extra stuff from the reply address.
Of course there are exceptions. This was sufficiently obvious that I
didn't think it was worth the trouble to type it.
Of course there are exceptions. This was sufficiently obvious that I
didn't think it was worth the trouble to type it.
What would you do here?
1. Use caller-remove when calling variadic functions (but still keep
to callee remove when calling functions with a fixed number of
arguments).
2. Have the callee remove any fixed parameters and the caller remove
any others it may have pushed.
Any preferences - especially where performance is important?
James
Not quite so obvious: Just _how_ do you make exceptions?
Do you want prototypes required for everything, and those
prototypes tied to machine architectures (FASTCALL)?
Sure, you can get a parser to recognize `printf()`, but what happens
when you want to do your own foo_print(), maybe as a wrapper?
ASM is great because of course you can do whatever you like,
and have whatever conventions suit a function. Just so long
as you keep them straight. Much more difficult for HLLs
which are required to be portable.
-- Robert
IIRC PASCAL uses this.
> or pass a pointer to a list of the parms.
Sounds like FORTRAN :)
> More work, but either would work.
True, but more housekeeping that ASMers love :)
Rather more than the savings of RET 4 vs add esp,4
-- Robert
For a number of reasons passing the length of the parameters pushed
should be avoided. Apart from the extra register usage the return
address will be on the stack with the parameters below it. You'd
effectively have to pop the return address, then adjust the stack and
then jump to the address that you popped before you adjusted the
stack.
The ret N instruction does this but only works with a constant number
of bytes to drop from the stack.
The other suggestion, a pointer to a parameter block, is better. If
the pointer is in a register a simple ret will return. If the pointer
is on the stack a ret 4 or similar would do.
James
Not any Pascal compiler I've seen (or at least examined the code it
produced). The compiler generates the code for both the call and the
return, and generates code so they match. Since nothing (except
built-in things like readln and writeln) accepts a variable number of
parameters, the called code knows the number of parameters
implicitly.
> > or pass a pointer to a list of the parms.
>
> Sounds like FORTRAN :)
Most Fortran compilers use pretty much the same calling convention as
most Pascal compilers. For example, at one time Microsoft C accepted
both 'pascal' and 'fortran' as keywords to specify calling
conventions for functions -- and the two were synonyms.
--
Later,
Jerry.
>
>In article <4ac20ccb$0$4958$9a6e...@unlimited.newshosting.com>,=20
>red...@ev1.net.invalid says...
>>=20
>> ArarghMai...@not.at.arargh.com wrote in part:
>> > Either pass the length of the parms pushed,=20
>>=20
>> IIRC PASCAL uses this.
>
>Not any Pascal compiler I've seen (or at least examined the code it=20
>produced). The compiler generates the code for both the call and the=20
>return, and generates code so they match. Since nothing (except=20
>built-in things like readln and writeln) accepts a variable number of=20
>parameters, the called code knows the number of parameters=20
>implicitly.
>=20
>> > or pass a pointer to a list of the parms. =20
>>=20
>> Sounds like FORTRAN :)
>
>Most Fortran compilers use pretty much the same calling convention as=20
>most Pascal compilers. For example, at one time Microsoft C accepted=20
>both 'pascal' and 'fortran' as keywords to specify calling=20
>conventions for functions -- and the two were synonyms.
Probably accepted 'basic' as well. All three have the same calling
conventions in microsoft 16-bit compiler products.
From alang.hlp (view in a fixed font):
C SYSCALL STDCALL BASIC FORTRAN PASCAL
+-----------------------------------------------+
Leading Underscore =A6 X =A6 =A6 X =A6 =A6 =A6=
=A6
+-------+-------+-------+-------+-------+-------=A6
Capitalize All =A6 =A6 =A6 =A6 X =A6 X =A6=
X =A6
+-------+-------+-------+-------+-------+-------=A6
Args Left to Right =A6 =A6 =A6 =A6 X =A6 X =A6=
X =A6
+-------+-------+-------+-------+-------+-------=A6
Args Right to Left =A6 X =A6 X =A6 X =A6 =A6 =A6=
=A6
+-------+-------+-------+-------+-------+-------=A6
Caller Stack Cleanup =A6 X =A6 =A6 * =A6 =A6 =A6=
=A6
+-------+-------+-------+-------+-------+-------=A6
BP Saved =A6 =A6 =A6 =A6 X =A6 X =A6=
X =A6
+-------+-------+-------+-------+-------+-------=A6
:VARARG Allowed =A6 X =A6 X =A6 X =A6 =A6 =A6=
=A6
+-----------------------------------------------+
* The STDCALL language type uses caller stack cleanup if the :VARARG
parameter is used. Otherwise, the called routine must clean up the
stack.
--=20
Option 1. Use callee-remove for fixed argument functions, and
caller-remove for variadic functions. That's only slightly more
complicated than the always-caller-remove solution.
The performance argument is a bit of a red herring -- after all, we're
talking about one additional instruction.