指针
#include <iostream>
using namespace std;
int * mac()
{
int *i=new int(10);
return i;
}
int macp(int *n)
{
cout<<*n<<endl;
}
int main()
{
int i=10;
int *p=&i;
int *pp=mac();
printf("%d\n",*p);
printf("%d\n",*pp);
return 0;
}
汇编代码
0x00005555555549e4 <+0>: push rbp
0x00005555555549e5 <+1>: mov rbp,rsp
0x00005555555549e8 <+4>: sub rsp,0x20
0x00005555555549ec <+8>: mov rax,QWORD PTR fs:0x28
0x00005555555549f5 <+17>: mov QWORD PTR [rbp-0x8],rax
0x00005555555549f9 <+21>: xor eax,eax
0x00005555555549fb <+23>: mov DWORD PTR [rbp-0x1c],0xa
=> 0x0000555555554a02 <+30>: lea rax,[rbp-0x1c]
0x0000555555554a06 <+34>: mov QWORD PTR [rbp-0x18],rax
0x0000555555554a0a <+38>: call 0x55555555498a <mac()>
0x0000555555554a0f <+43>: mov QWORD PTR [rbp-0x10],rax
0x0000555555554a13 <+47>: mov rax,QWORD PTR [rbp-0x18]
0x0000555555554a17 <+51>: mov eax,DWORD PTR [rax]
0x0000555555554a19 <+53>: mov esi,eax
0x0000555555554a1b <+55>: lea rdi,[rip+0x123] # 0x555555554b45
0x0000555555554a22 <+62>: mov eax,0x0
0x0000555555554a27 <+67>: call 0x555555554800 <printf@plt>
0x0000555555554a2c <+72>: mov rax,QWORD PTR [rbp-0x10]
0x0000555555554a30 <+76>: mov eax,DWORD PTR [rax]
0x0000555555554a32 <+78>: mov esi,eax
0x0000555555554a34 <+80>: lea rdi,[rip+0x10a] # 0x555555554b45
0x0000555555554a3b <+87>: mov eax,0x0
0x0000555555554a40 <+92>: call 0x555555554800 <printf@plt>
0x0000555555554a45 <+97>: mov eax,0x0
0x0000555555554a4a <+102>: mov rdx,QWORD PTR [rbp-0x8]
0x0000555555554a4e <+106>: xor rdx,QWORD PTR fs:0x28
0x0000555555554a57 <+115>: je 0x555555554a5e <main()+122>
0x0000555555554a59 <+117>: call 0x555555554840 <__stack_chk_fail@plt>
0x0000555555554a5e <+122>: leave
0x0000555555554a5f <+123>: ret
End of assembler dump.
指针赋值
int *p=&i;
0x0000555555554a02 <+30>: lea rax,[rbp-0x1c]
0x0000555555554a06 <+34>: mov QWORD PTR [rbp-0x18],rax
[rbp-0x1c]为i的首地址,lea指令取其地址而后放入rax中
[rbp-0x18]为指针p的首地址,将rax中的值复制到其中完成指针的赋值
函数返回值
mac函数汇编代码
Dump of assembler code for function mac():
=> 0x000055555555498a <+0>: push rbp
0x000055555555498b <+1>: mov rbp,rsp
0x000055555555498e <+4>: sub rsp,0x10
0x0000555555554992 <+8>: mov edi,0x4
0x0000555555554997 <+13>: call 0x555555554820 <_Znwm@plt>
0x000055555555499c <+18>: mov DWORD PTR [rax],0xa
0x00005555555549a2 <+24>: mov QWORD PTR [rbp-0x8],rax
0x00005555555549a6 <+28>: mov rax,QWORD PTR [rbp-0x8]
0x00005555555549aa <+32>: leave
0x00005555555549ab <+33>: ret
End of assembler dump.
mov rax,QWORD PTR [rbp-0x8] 将返回值存入rax寄存器中
mov QWORD PTR [rbp-0x10],rax 将返回值复制到指针pp中
函数参数
0x0000555555554a13 <+47>: mov rax,QWORD PTR [rbp-0x18]//将指针中保存的地址放入rax中
0x0000555555554a17 <+51>: mov eax,DWORD PTR [rax]//取出值
0x0000555555554a19 <+53>: mov esi,eax//利用地址取出值,该参数传递方法为寄存器传递
0x0000555555554a1b <+55>: lea rdi,[rip+0x123] # 0x555555554b45
0x0000555555554a22 <+62>: mov eax,0x0
0x0000555555554a27 <+67>: call 0x555555554800 <printf@plt>
引用
#include <iostream>
using namespace std;
int& mac()
{
int *i=new int(10);
return *i;
}
int macp(int &n)
{
cout<<n<<endl;
}
int main()
{
int i= 10;
int &p=i;
p=mac();
macp(p);
printf("%d\n",p);
return 0;
}
汇编代码
(gdb) disassemble
Dump of assembler code for function main():
0x00005555555549e4 <+0>: push rbp
0x00005555555549e5 <+1>: mov rbp,rsp
0x00005555555549e8 <+4>: sub rsp,0x20
0x00005555555549ec <+8>: mov rax,QWORD PTR fs:0x28
0x00005555555549f5 <+17>: mov QWORD PTR [rbp-0x8],rax
0x00005555555549f9 <+21>: xor eax,eax
=> 0x00005555555549fb <+23>: mov DWORD PTR [rbp-0x14],0xa
0x0000555555554a02 <+30>: lea rax,[rbp-0x14]
0x0000555555554a06 <+34>: mov QWORD PTR [rbp-0x10],rax
0x0000555555554a0a <+38>: call 0x55555555498a <mac()>
0x0000555555554a0f <+43>: mov edx,DWORD PTR [rax]
0x0000555555554a11 <+45>: mov rax,QWORD PTR [rbp-0x10]
0x0000555555554a15 <+49>: mov DWORD PTR [rax],edx
0x0000555555554a17 <+51>: mov rax,QWORD PTR [rbp-0x10]
0x0000555555554a1b <+55>: mov rdi,rax
0x0000555555554a1e <+58>: call 0x5555555549ac <macp(int&)>
0x0000555555554a23 <+63>: mov rax,QWORD PTR [rbp-0x10]
0x0000555555554a27 <+67>: mov eax,DWORD PTR [rax]
0x0000555555554a29 <+69>: mov esi,eax
0x0000555555554a2b <+71>: lea rdi,[rip+0x113] # 0x555555554b45
0x0000555555554a32 <+78>: mov eax,0x0
0x0000555555554a37 <+83>: call 0x555555554800 <printf@plt>
0x0000555555554a3c <+88>: mov eax,0x0
0x0000555555554a41 <+93>: mov rcx,QWORD PTR [rbp-0x8]
0x0000555555554a45 <+97>: xor rcx,QWORD PTR fs:0x28
0x0000555555554a4e <+106>: je 0x555555554a55 <main()+113>
0x0000555555554a50 <+108>: call 0x555555554840 <__stack_chk_fail@plt>
0x0000555555554a55 <+113>: leave
0x0000555555554a56 <+114>: ret
End of assembler dump.
引用初始化赋值
0x0000555555554a02 <+30>: lea rax,[rbp-0x14]
0x0000555555554a06 <+34>: mov QWORD PTR [rbp-0x10],rax
对比指针赋值可以看出引用的赋值和指针的赋值是相同的方法
函数返回值
mac函数汇编
Dump of assembler code for function mac():
0x000055555555498a <+0>: push rbp
0x000055555555498b <+1>: mov rbp,rsp
0x000055555555498e <+4>: sub rsp,0x10
0x0000555555554992 <+8>: mov edi,0x4
0x0000555555554997 <+13>: call 0x555555554820 <_Znwm@plt>
0x000055555555499c <+18>: mov DWORD PTR [rax],0xa
0x00005555555549a2 <+24>: mov QWORD PTR [rbp-0x8],rax
0x00005555555549a6 <+28>: mov rax,QWORD PTR [rbp-0x8]//将变量地址存入rax作为函数返回值
=> 0x00005555555549aa <+32>: leave
0x00005555555549ab <+33>: ret
End of assembler dump.
0x0000555555554a0a <+38>: call 0x55555555498a <mac()>
0x0000555555554a0f <+43>: mov edx,DWORD PTR [rax]//取出rax中地址空间的值
0x0000555555554a11 <+45>: mov rax,QWORD PTR [rbp-0x10]//将p引用中保存的值取出,该值为变量i的地址
(gdb) info registers eax
eax 0xffffddcc -8756
(gdb) p $rbp-0x14
$3 = (void *) 0x7fffffffddcc
0x0000555555554a15 <+49>: mov DWORD PTR [rax],edx//赋值给变量i
和指针相对比可得:指针是直接改变其保存的变量地址,引用是通过保存的变量地址给被引用的变量赋值
另外一种函数返回值
函数原型
#include <iostream>
using namespace std;
int num;
int& mac()
{
num=10;
return num;
#不能返回栈中元素的引用,因为函数调用结束后栈空间会释放,此处只是举例
}
int main()
{
int i= 10;
int &p=i;
p=mac();
cout<<i<<endl;
return 0;
}
汇编
Dump of assembler code for function main():
0x0000555555554911 <+0>: push rbp
0x0000555555554912 <+1>: mov rbp,rsp
0x0000555555554915 <+4>: sub rsp,0x20
0x0000555555554919 <+8>: mov rax,QWORD PTR fs:0x28
0x0000555555554922 <+17>: mov QWORD PTR [rbp-0x8],rax
0x0000555555554926 <+21>: xor eax,eax
=> 0x0000555555554928 <+23>: mov DWORD PTR [rbp-0x14],0xa
0x000055555555492f <+30>: lea rax,[rbp-0x14]
0x0000555555554933 <+34>: mov QWORD PTR [rbp-0x10],rax
0x0000555555554937 <+38>: call 0x5555555548fa <mac()>
0x000055555555493c <+43>: mov edx,DWORD PTR [rax]
0x000055555555493e <+45>: mov rax,QWORD PTR [rbp-0x10]
0x0000555555554942 <+49>: mov DWORD PTR [rax],edx
0x0000555555554944 <+51>: mov eax,DWORD PTR [rbp-0x14]
0x0000555555554947 <+54>: mov esi,eax
0x0000555555554949 <+56>: lea rdi,[rip+0x2006d0] # 0x555555755020 <_ZSt4cout@@GLIBCXX_3.4>
0x0000555555554950 <+63>: call 0x5555555547d0 <_ZNSolsEi@plt>
0x0000555555554955 <+68>: mov rdx,rax
0x0000555555554958 <+71>: mov rax,QWORD PTR [rip+0x200671] # 0x555555754fd0
0x000055555555495f <+78>: mov rsi,rax
0x0000555555554962 <+81>: mov rdi,rdx
0x0000555555554965 <+84>: call 0x5555555547a0 <_ZNSolsEPFRSoS_E@plt>
0x000055555555496a <+89>: mov eax,0x0
0x000055555555496f <+94>: mov rcx,QWORD PTR [rbp-0x8]
0x0000555555554973 <+98>: xor rcx,QWORD PTR fs:0x28
0x000055555555497c <+107>: je 0x555555554983 <main()+114>
0x000055555555497e <+109>: call 0x5555555547b0 <__stack_chk_fail@plt>
0x0000555555554983 <+114>: leave
0x0000555555554984 <+115>: ret
End of assembler dump.
Dump of assembler code for function mac():
0x00005555555548fa <+0>: push rbp
0x00005555555548fb <+1>: mov rbp,rsp
0x00005555555548fe <+4>: mov DWORD PTR [rip+0x20082c],0xe # 0x555555755134 <num>
0x0000555555554908 <+14>: lea rax,[rip+0x200825] # 0x555555755134 <num>
0x000055555555490f <+21>: pop rbp
0x0000555555554910 <+22>: ret
End of assembler dump.
0x0000555555554908 <+14>: lea rax,[rip+0x200825] # 0x555555755134 <num>
和之前相同同样是将地址放入rax中为后进行相同的操作
函数参数
0x0000555555554a17 <+51>: mov rax,QWORD PTR [rbp-0x10]
0x0000555555554a1b <+55>: mov rdi,rax
0x0000555555554a1e <+58>: call 0x5555555549ac <macp(int&)>
对比可发现引用直接用其保存的地址将值取出,没有将地址取出保存至寄存器,而后利用寄存器取出值,即没有解引用这 一步
自增等操作
引用是弱化的指针,有很多相似的地方,不同的是当指针进行++操作时改变的是其保存的地址值,而引用则要通过地址寻找被引用的变量并改边其值
例如
#include <iostream>
using namespace std;
int main()
{
int i=10;
int *p=&i;
int &pp=i;
p++;
pp++;
return 0;
}
Dump of assembler code for function main():
0x00005555555547aa <+0>: push rbp
0x00005555555547ab <+1>: mov rbp,rsp
0x00005555555547ae <+4>: sub rsp,0x20
0x00005555555547b2 <+8>: mov rax,QWORD PTR fs:0x28
0x00005555555547bb <+17>: mov QWORD PTR [rbp-0x8],rax
0x00005555555547bf <+21>: xor eax,eax
0x00005555555547c1 <+23>: mov DWORD PTR [rbp-0x1c],0xa
0x00005555555547c8 <+30>: lea rax,[rbp-0x1c]
0x00005555555547cc <+34>: mov QWORD PTR [rbp-0x18],rax
0x00005555555547d0 <+38>: lea rax,[rbp-0x1c]
0x00005555555547d4 <+42>: mov QWORD PTR [rbp-0x10],rax
0x00005555555547d8 <+46>: add QWORD PTR [rbp-0x18],0x4
0x00005555555547dd <+51>: mov rax,QWORD PTR [rbp-0x10]
0x00005555555547e1 <+55>: mov eax,DWORD PTR [rax]
0x00005555555547e3 <+57>: lea edx,[rax+0x1]
0x00005555555547e6 <+60>: mov rax,QWORD PTR [rbp-0x10]
0x00005555555547ea <+64>: mov DWORD PTR [rax],edx
0x00005555555547ec <+66>: mov eax,0x0
0x00005555555547f1 <+71>: mov rcx,QWORD PTR [rbp-0x8]
0x00005555555547f5 <+75>: xor rcx,QWORD PTR fs:0x28
0x00005555555547fe <+84>: je 0x555555554805 <main()+91>
0x0000555555554800 <+86>: call 0x555555554670 <__stack_chk_fail@plt>
0x0000555555554805 <+91>: leave
0x0000555555554806 <+92>: ret
End of assembler dump.
指针++
0x00005555555547d8 <+46>: add QWORD PTR [rbp-0x18],0x4
直接改变其保存的地址值,进行+4操作
引用++
0x00005555555547dd <+51>: mov rax,QWORD PTR [rbp-0x10]
0x00005555555547e1 <+55>: mov eax,DWORD PTR [rax]
0x00005555555547e3 <+57>: lea edx,[rax+0x1]//这里edx等于11
0x00005555555547e6 <+60>: mov rax,QWORD PTR [rbp-0x10] //取回i的地址
0x00005555555547ea <+64>: mov DWORD PTR [rax],edx//赋值