C ++编译器函数调用

时间:2014-06-20 18:32:33

标签: c++ gcc asmx disassembly

为什么编译器在函数调用之前输入了这么多命令(请看下面的链接)?据我了解,它应该在调用之前只传递函数参数。

struct A{
  int c = 5;
void test(unsigned int a){
  a++;
  c++;
}
};

struct C{
  int k =2;
  A a;
};

struct D{
  int k =2;
  C c;
};

struct B{
  int k =2;
 D d;
};

void test(unsigned int a){
  a++;
}

    B *b = new B();
A *ae = new A();

int main() 
{
  int a = 1;
  A ai;
  B bi;
  C ci;

  // 2 operations (why not pop/push ?)
  // movl   -36(%rbp), %eax
  // movl   %eax, %edi
  // call   test(unsigned int)
  test(a);

  // 4 operations (why 4? we pass something else?)
  // movl   -36(%rbp), %edx
  // leaq   -48(%rbp), %rax
  // movl   %edx, %esi
  // movq   %rax, %rdi
  // call   A::test(unsigned int)
  ai.test(a);
  ae->test(a);


  // 5 operations before call (what a hell is going here?, why that "addq" ?)
  // movl   -36(%rbp), %eax
  // leaq   -32(%rbp), %rdx
  // addq   $4, %rdx
  // movl   %eax, %esi
  // movq   %rdx, %rdi
  // call   A::test(unsigned int)
  ci.a.test(a);
  bi.d.c.a.test(a);
  b->d.c.a.test(a);
  // no matter how long this chain will be - it will always took 5 operations
}

http://goo.gl/smFSA6

为什么当我们调用类成员时,需要另外4个命令来准备调用?我们还加载对象地址进行注册?

最后一个案例有5个操作,就在我之外......

P.S。在我年轻的时候,通常,我们把函数参数叠加(推),而不是读(pop)。那么,我们通过寄存器传递参数?

1 个答案:

答案 0 :(得分:3)

这是正常的。在装配中,我的建筑通常只做一件事。例如,在最后一种情况下:

movl   -36(%rbp), %eax       ; move a to %eax
leaq   -32(%rbp), %rdx       ; move & ci  to %rdx
addq   $4, %rdx              ; set %rdx to ci->a = ci + offset of a
movl   %eax, %esi            ; move a from %eax to %esi (second parameter) 
movq   %rdx, %rdi            ; move ci->a from %rdx to %rdi (first parameter)
call   A::test(unsigned int) ; call A::test

在64位linux系统中,函数参数不再在堆栈上传输,前6个整数参数在%rdi%rsi%rdx%rcx中传输, %r8%r9注册。浮点值使用%xmm0 - %xmm7寄存器,其他寄存器在堆栈中传输。

当然,局部变量位于堆栈中,可通过%rbp

访问