class A
{
public:
long a1;
long a2;
public:
A(long _a1, long _a2)
{
a1 = _a1;
a2 = _a2;
}
A(const A &_a)
{
a1 = _a.a1;
a2 = _a.a2;
}
};
int addm(long x1, long x2, long x3, long x4, A a)
{
return a.a1 + a.a2;
}
int main()
{
long s = 1;
A a(1L, 2L);
s = addm(10, 11, 12, 13, a);
}
导出汇编
0x00000001004010a9 <+0>: push %rbp
0x00000001004010aa <+1>: mov %rsp,%rbp
0x00000001004010ad <+4>: sub $0x60,%rsp
0x00000001004010b1 <+8>: callq 0x1004011b0 <__main>
=> 0x00000001004010b6 <+13>: movq $0x1,-0x8(%rbp)
0x00000001004010be <+21>: lea -0x30(%rbp),%rax // 存放变量a的地址
0x00000001004010c2 <+25>: mov $0x2,%r8d // 参数入栈
0x00000001004010c8 <+31>: mov $0x1,%edx // 参数入栈
0x00000001004010cd <+36>: mov %rax,%rcx // 参数入栈
0x00000001004010d0 <+39>: callq 0x1004017d0 <A::A(long, long)>
0x00000001004017d0 <+0>: push %rbp
0x00000001004017d1 <+1>: mov %rsp,%rbp
0x00000001004017d4 <+4>: mov %rcx,0x10(%rbp) // 参数入栈
0x00000001004017d8 <+8>: mov %rdx,0x18(%rbp) // 参数入栈
0x00000001004017dc <+12>: mov %r8,0x20(%rbp) // 参数入栈
=> 0x00000001004017e0 <+16>: mov 0x10(%rbp),%rax // 接下来通过变量a的地址进行成员变量赋值
0x00000001004017e4 <+20>: mov 0x18(%rbp),%rdx
0x00000001004017e8 <+24>: mov %rdx,(%rax)
0x00000001004017eb <+27>: mov 0x10(%rbp),%rax
0x00000001004017ef <+31>: mov 0x20(%rbp),%rdx
0x00000001004017f3 <+35>: mov %rdx,0x8(%rax)
0x00000001004017f7 <+39>: nop
0x00000001004017f8 <+40>: pop %rbp
0x00000001004017f9 <+41>: retq
0x00000001004010d5 <+44>: lea -0x30(%rbp),%rdx // 变量a的地址
0x00000001004010d9 <+48>: lea -0x20(%rbp),%rax // 函数传值,需要对传入的对象进行复制。这里是存放复制对象存放的地址
0x00000001004010dd <+52>: mov %rax,%rcx
0x00000001004010e0 <+55>: callq 0x1004017a0 <A::A(A const&)>
0x00000001004017a0 <+0>: push %rbp
0x00000001004017a1 <+1>: mov %rsp,%rbp
0x00000001004017a4 <+4>: mov %rcx,0x10(%rbp) // 参数入栈,复制对象的地址
0x00000001004017a8 <+8>: mov %rdx,0x18(%rbp) // 参数入栈,变量a的地址
=> 0x00000001004017ac <+12>: mov 0x18(%rbp),%rax // 地址
0x00000001004017b0 <+16>: mov (%rax),%rdx // 按照地址取值
0x00000001004017b3 <+19>: mov 0x10(%rbp),%rax // 复制到的地址
0x00000001004017b7 <+23>: mov %rdx,(%rax) // 值复制到指定地址
0x00000001004017ba <+26>: mov 0x18(%rbp),%rax
0x00000001004017be <+30>: mov 0x8(%rax),%rdx
0x00000001004017c2 <+34>: mov 0x10(%rbp),%rax
0x00000001004017c6 <+38>: mov %rdx,0x8(%rax)
0x00000001004017ca <+42>: nop
0x00000001004017cb <+43>: pop %rbp
0x00000001004017cc <+44>: retq // 当复制构造函数执行完成,一个临时变量被存放在了-0x20(%rbp)的位置
0x00000001004010e5 <+60>: lea -0x20(%rbp),%rax // 之后的调用函数,会操作这个复制的临时变量
0x00000001004010e9 <+64>: mov %rax,0x20(%rsp) // 复制对象的地址入栈,对应下一个函数栈0x30(%rbp)的地址
0x00000001004010ee <+69>: mov $0xd,%r9d // x86-64参数入栈会先使用四个寄存器,用四个参数提前消耗掉
0x00000001004010f4 <+75>: mov $0xc,%r8d //
0x00000001004010fa <+81>: mov $0xb,%edx //
0x00000001004010ff <+86>: mov $0xa,%ecx //
0x0000000100401104 <+91>: callq 0x100401080 <addm(long, long, long, long, A)>
0x0000000100401080 <+0>: push %rbp
0x0000000100401081 <+1>: mov %rsp,%rbp
0x0000000100401084 <+4>: mov %rcx,0x10(%rbp) // 四个参数入栈
0x0000000100401088 <+8>: mov %rdx,0x18(%rbp) // 四个参数入栈
0x000000010040108c <+12>: mov %r8,0x20(%rbp) // 四个参数入栈
0x0000000100401090 <+16>: mov %r9,0x28(%rbp) // 四个参数入栈
=> 0x0000000100401094 <+20>: mov 0x30(%rbp),%rax // 接下来通过复制对象的地址获取复制对象并进行计算
0x0000000100401098 <+24>: mov (%rax),%rax
0x000000010040109b <+27>: mov %eax,%edx
0x000000010040109d <+29>: mov 0x30(%rbp),%rax
0x00000001004010a1 <+33>: mov 0x8(%rax),%rax
0x00000001004010a5 <+37>: add %edx,%eax
0x00000001004010a7 <+39>: pop %rbp
0x00000001004010a8 <+40>: retq
0x0000000100401109 <+96>: cltq
0x000000010040110b <+98>: mov %rax,-0x8(%rbp)
0x000000010040110f <+102>: mov $0x0,%eax
0x0000000100401114 <+107>: add $0x60,%rsp
0x0000000100401118 <+111>: pop %rbp
0x0000000100401119 <+112>: retq
栈内存示意
说明 | 地址 |
---|---|
0 main_rbp 存放上一个函数的rbp | 0xffffcbe0 |
1 变量s=1 | |
2 | |
3 | |
4 -0x20 main_rbp 复制对象地址 | |
5 a2=2 | |
6 -0x30 main_rbp 变量a的地址 a1=1 | |
7 | |
8 复制对象地址入栈 | 0xffffcb80 -0x40 main_rbp |
9 x | |
10 参数入栈 参数2 0x20 Ac_rbp x | |
11 参数入栈 参数1 0x18 Ac_rbp x | |
12 参数入栈 变量a的地址 0x10 Ac_rbp x | 0xffffcb80 -0x60 main_rbp |
13 callq 存放上一个函数执行到的指令 | |
14 Ac_rbp Acc_rbp addm_rbp 这三个函数的rbp使用同一个地址 | 0xffffcb70 |