Page 1 of 1

help on GCC calling convention

Posted: Wed May 25, 2011 3:53 am
by yuq
Hello,

I'm studying the GCC calling convention. I compile a C function:

Code: Select all

int add2(int a, int b)  //add two numbers
{
  int tmp;
  tmp = a+b;
  return tmp;
}
using GCC 4.4.3 with no optimization: gcc -S add2.c. And I got:

Code: Select all

add2:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$16, %esp
	movl	12(%ebp), %eax
	movl	8(%ebp), %edx
	leal	(%edx,%eax), %eax
	movl	%eax, -4(%ebp)
	movl	-4(%ebp), %eax
	leave
	ret
So the stack seems like this:

Code: Select all

      |     arg b    |             |     stack grow direction
      +--------------+             |
      |     arg a    |            \ /
      +--------------+
      |  return eip  |
      +--------------+
      |     ebp      |
      +--------------+
      |      ??      |
      +--------------+
      |      tmp     |
      +--------------+
      |      ??      |
      +--------------+
      |      ??      |
      +--------------+
I don't understand why the GCC reserves 12 Byte in the stack. What the "??" place store?

Re: help on GCC calling convention

Posted: Wed May 25, 2011 4:56 am
by mindentropy
Maybe stack alignment. Try it without the alignment option. The amount of alignment depends on the processors.

Re: help on GCC calling convention

Posted: Wed May 25, 2011 5:57 am
by Owen
My guess is that GCC has assigned a stack slot for every variable, then added one for alignment purposes (IIRC i386 SysV ABI defines 8 byte aligned stacks). With no optimizations enabled, GCC generates pretty dumb code.

Also: tmp is immediately below EBP; there is no gap between them

Re: help on GCC calling convention

Posted: Wed May 25, 2011 7:47 am
by yuq
Owen wrote: Also: tmp is immediately below EBP; there is no gap between them
Yes, you are right. The tmp is following ebp.

I have tried some different cases and find a rule: in function which will call other functions, the stack is 16 byte aligned. In function which won't call other functions (like the above add2()), the stack is increased by 16 byte when increase local variables. But plus the first pushed ebp, the stack seems not aligned. And I find a new question:

Code: Select all

int add3(int a, int b, int c)

int main()
{
  int c;
  c = add3(1, 2, 3);
  return c;
}
I got:

Code: Select all

main:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$28, %esp
	movl	$3, 8(%esp)
	movl	$2, 4(%esp)
	movl	$1, (%esp)
	call	add3
	movl	%eax, -4(%ebp)
	movl	-4(%ebp), %eax
	leave
	ret
But function:

Code: Select all

int add3(int a, int b, int c);

int add(void)
{
  int c;
  c = add3(1, 2, 3);
  return c;
}
I got:

Code: Select all

add:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$40, %esp
	movl	$3, 8(%esp)
	movl	$2, 4(%esp)
	movl	$1, (%esp)
	call	add3
	movl	%eax, -12(%ebp)
	movl	-12(%ebp), %eax
	leave
	ret
It seems the main() function is special? The alignment is different between main() and add(). Why?