汇编的角度看c++构造函数和复制构造函数

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 存放上一个函数的rbp0xffffcbe0
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 x0xffffcb80 -0x60 main_rbp
13 callq 存放上一个函数执行到的指令
14 Ac_rbp Acc_rbp addm_rbp 这三个函数的rbp使用同一个地址0xffffcb70
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值