Reputation: 55
I have an assembly application for Linux x64 where I pass arguments to the functions via registers, thus I'm using a certain calling convention, in this case fastcall
. Now I want to call a C function from the assembly application which, say, expects 10 arguments.
Do I have to switch to cdecl
for that and pass the arguments via stack regardless of the fact everywhere else in my application I'm passing them via registers? Is it allowed to mix calling conventions in one application?
Upvotes: 0
Views: 310
Reputation: 93014
I assume that by fastcall, you mean the amd64 calling convention used by the SysV ABI (i.e. what Linux uses) where the first few arguments are passed in rdi
, rsi
, and rdx
.
The ABI is slightly complicated, the following is a simplification. You might want to read the specification for details.
Generally speaking, the first few (leftmost) integer or pointer arguments are placed into the registers rdi
, rsi
, rdx
, rcx
, r8
, and r9
. Floating point arguments are passed in xmm0
to xmm7
. If the register space is exhausted, additional arguments are passed through the stack from right to left. For example, to call a function with 10 integer arguments:
foo(a, b, c, d, e, f, g, h, i, k);
you would need code like this:
mov $a,%edi
mov $b,%esi
mov $c,%edx
mov $d,%ecx
mov $e,%r8d
mov $f,%r9d
push $k
push $i
push $h
push $g
call foo
add $32,%rsp
For your concrete example, of getnameinfo
:
int getnameinfo(
const struct sockaddr *sa,
socklen_t salen,
char *host,
size_t hostlen,
char *serv,
size_t servlen,
int flags);
You would pass sa
in rdi
, salen
in rsi
, host
in rdx
, hostlen
in rcx
, serv
in r8
, servlen
in r9
and flags
on the stack.
Upvotes: 3
Reputation: 6063
You can, but you don't need to.
__attribute__((fastcall))
only asks for the first two parameters to be passed in registers - everything else will anyhow automatically be passed on the stack, just like with cdecl
. This is done in order to not limit the number of parameters that can be given to a function by chosing a certain calling convention.
In your example with 10 parameters for a function that is called with the fastcall
calling convention, the first two parameters will be passed in registers, the remaining 8 automatically on the stack, just like with standard calling convention.
As you have chosen to use fastcall
for all your other functions, I do not see a reason why you'd want to change this for one specific function.
Upvotes: -2
Reputation: 5920
Yes of course. Calling convention is applied on per-function basis. This is a perfectly valid application:
int __stdcall func1()
{
return(1);
}
int __fastcall func2()
{
return(2);
}
int __cdecl main(void)
{
func1();
func2();
return(0);
}
Upvotes: 2