指针与引用

int main()
{
000000013FA01010  push        rdi  
000000013FA01012  sub         rsp,50h  
000000013FA01016  mov         rdi,rsp  
000000013FA01019  mov         ecx,14h  
000000013FA0101E  mov         eax,0CCCCCCCCh  
000000013FA01023  rep stos    dword ptr [rdi]  
    int x=0x12345678;
000000013FA01025  mov         dword ptr [x],12345678h  
    //取地址到指针变量p中
    int *p=&x;
000000013FA0102D  lea         rax,[x]  
000000013FA01032  mov         qword ptr [p],rax  
    int y=*p;
000000013FA01037  mov         rax,qword ptr [p]  
000000013FA0103C  mov         eax,dword ptr [rax]  
000000013FA0103E  mov         dword ptr [y],eax  
    printf("%d",y);
000000013FA01042  mov         edx,dword ptr [y]  
000000013FA01046  lea         rcx,[__xi_z+150h (013FA068C0h)]  
000000013FA0104D  call        qword ptr [__imp_printf (013FA0B540h)]  
    return 0;
000000013FA01053  xor         eax,eax  
}
000000013FA01055  mov         edi,eax  
000000013FA01057  mov         rcx,rsp  
000000013FA0105A  lea         rdx,[__xi_z+1A0h (013FA06910h)]  
000000013FA01061  call        _RTC_CheckStackVars (013FA010D0h)  
000000013FA01066  mov         eax,edi  
000000013FA01068  add         rsp,50h  
000000013FA0106C  pop         rdi  
000000013FA0106D  ret  

解引用在汇编中要取两次“地址”。

指针p是一个指针变量,空间内存放x的地址。

下面看看引用:

可以看到,两者反汇编代码是相同的,不同的是解引用是由编译器操作的。

我们在定义时,定义为引用,编译器就知道这是一个需要编译器寻址的指针。例如printf时,不需要写成*p。

看下面的代码:

void _swap(int a,int b)
{
    int temp;
    temp=a;
    a=b;
    b=temp;

}
void swap1(int *a,int *b)
{
    int temp;
    temp=*a;
    *a=*b;
    *b=temp;

}
void swap2(int &a,int &b)
{
    int temp=a;
    a=b;
    b=temp;
}
int main()
{
    int x,y;
    x=10;
    y=20;
    _swap(x,y);
    printf("%d,%d\n",x,y);
    swap1(&x,&y);
    printf("%d,%d\n",x,y);
    swap2(x,y);
    printf("%d,%d\n",x,y);

    return 0;
}

vc中的反汇编代码:

void _swap(int a,int b)
{
000000013F1F1030  mov         dword ptr [rsp+10h],edx  
000000013F1F1034  mov         dword ptr [rsp+8],ecx  
000000013F1F1038  push        rdi  
000000013F1F1039  sub         rsp,10h  
000000013F1F103D  mov         rdi,rsp  
000000013F1F1040  mov         ecx,4  
000000013F1F1045  mov         eax,0CCCCCCCCh  
000000013F1F104A  rep stos    dword ptr [rdi]  
000000013F1F104C  mov         ecx,dword ptr [a]  
    int temp;
    temp=a;
000000013F1F1050  mov         eax,dword ptr [a]  
000000013F1F1054  mov         dword ptr [rsp],eax  
    a=b;
000000013F1F1057  mov         eax,dword ptr [b]  
000000013F1F105B  mov         dword ptr [a],eax  
    b=temp;
000000013F1F105F  mov         eax,dword ptr [rsp]  
000000013F1F1062  mov         dword ptr [b],eax  

}
000000013F1F1066  add         rsp,10h  
000000013F1F106A  pop         rdi  
000000013F1F106B  ret  
/////////////////////////////////
void swap1(int *a,int *b)
{
000000013F1F1080  mov         qword ptr [rsp+10h],rdx  
000000013F1F1085  mov         qword ptr [rsp+8],rcx  
000000013F1F108A  push        rdi  
000000013F1F108B  sub         rsp,10h  
000000013F1F108F  mov         rdi,rsp  
000000013F1F1092  mov         ecx,4  
000000013F1F1097  mov         eax,0CCCCCCCCh  
000000013F1F109C  rep stos    dword ptr [rdi]  
000000013F1F109E  mov         rcx,qword ptr [a]  
    int temp;
    temp=*a;
000000013F1F10A3  mov         rax,qword ptr [a]  
000000013F1F10A8  mov         eax,dword ptr [rax]  
000000013F1F10AA  mov         dword ptr [rsp],eax  
    *a=*b;
000000013F1F10AD  mov         rax,qword ptr [a]  
000000013F1F10B2  mov         rcx,qword ptr [b]  
000000013F1F10B7  mov         ecx,dword ptr [rcx]  
000000013F1F10B9  mov         dword ptr [rax],ecx  
    *b=temp;
000000013F1F10BB  mov         rax,qword ptr [b]  
000000013F1F10C0  mov         ecx,dword ptr [rsp]  
000000013F1F10C3  mov         dword ptr [rax],ecx  

}
000000013F1F10C5  add         rsp,10h  
000000013F1F10C9  pop         rdi  
000000013F1F10CA  ret  
//////////////////////////////////
void swap2(int &a,int &b)
{
000000013F1F10E0  mov         qword ptr [rsp+10h],rdx  
000000013F1F10E5  mov         qword ptr [rsp+8],rcx  
000000013F1F10EA  push        rdi  
000000013F1F10EB  sub         rsp,10h  
000000013F1F10EF  mov         rdi,rsp  
000000013F1F10F2  mov         ecx,4  
000000013F1F10F7  mov         eax,0CCCCCCCCh  
000000013F1F10FC  rep stos    dword ptr [rdi]  
000000013F1F10FE  mov         rcx,qword ptr [a]  
    int temp=a;
000000013F1F1103  mov         rax,qword ptr [a]  
000000013F1F1108  mov         eax,dword ptr [rax]  
000000013F1F110A  mov         dword ptr [rsp],eax  
    a=b;
000000013F1F110D  mov         rax,qword ptr [a]  
000000013F1F1112  mov         rcx,qword ptr [b]  
000000013F1F1117  mov         ecx,dword ptr [rcx]  
000000013F1F1119  mov         dword ptr [rax],ecx  
    b=temp;
000000013F1F111B  mov         rax,qword ptr [b]  
000000013F1F1120  mov         ecx,dword ptr [rsp]  
000000013F1F1123  mov         dword ptr [rax],ecx  
}
000000013F1F1125  add         rsp,10h  
000000013F1F1129  pop         rdi  
000000013F1F112A  ret  
//////////////////////////////////
int main()
{
000000013F541140  push        rdi  
000000013F541142  sub         rsp,60h  
000000013F541146  mov         rdi,rsp  
000000013F541149  mov         ecx,18h  
000000013F54114E  mov         eax,0CCCCCCCCh  
000000013F541153  rep stos    dword ptr [rdi]  
    int x,y;
    x=10;
000000013F541155  mov         dword ptr [x],0Ah  
    y=20;
000000013F54115D  mov         dword ptr [y],14h  
    _swap(x,y);
000000013F541165  mov         edx,dword ptr [y]  
000000013F541169  mov         ecx,dword ptr [x]  
000000013F54116D  call        _swap (013F541005h)  
    printf("%d,%d\n",x,y);
000000013F541172  mov         r8d,dword ptr [y]  
000000013F541177  mov         edx,dword ptr [x]  
000000013F54117B  lea         rcx,[__xi_z+150h (013F5468C0h)]  
000000013F541182  call        qword ptr [__imp_printf (013F54B540h)]  
    swap1(&x,&y);
000000013F541188  lea         rdx,[y]  
000000013F54118D  lea         rcx,[x]  
000000013F541192  call        swap1 (013F54100Ah)  
    printf("%d,%d\n",x,y);
000000013F541197  mov         r8d,dword ptr [y]  
000000013F54119C  mov         edx,dword ptr [x]  
000000013F5411A0  lea         rcx,[__xi_z+158h (013F5468C8h)]  
000000013F5411A7  call        qword ptr [__imp_printf (013F54B540h)]  
    swap2(x,y);
000000013F5411AD  lea         rdx,[y]  
000000013F5411B2  lea         rcx,[x]  
000000013F5411B7  call        swap2 (013F54100Fh)  
    printf("%d,%d\n",x,y);
000000013F5411BC  mov         r8d,dword ptr [y]  
000000013F5411C1  mov         edx,dword ptr [x]  
000000013F5411C5  lea         rcx,[__xi_z+160h (013F5468D0h)]  
000000013F5411CC  call        qword ptr [__imp_printf (013F54B540h)]  

    return 0;
000000013F5411D2  xor         eax,eax  
}
000000013F5411D4  mov         edi,eax  
000000013F5411D6  mov         rcx,rsp  
000000013F5411D9  lea         rdx,[__xi_z+1F0h (013F546960h)]  
000000013F5411E0  call        _RTC_CheckStackVars (013F541290h)  
000000013F5411E5  mov         eax,edi  
000000013F5411E7  add         rsp,60h  
}
000000013F5411EB  pop         rdi  
000000013F5411EC  ret  

在这上面看不出什么有价值的东西,看看IDA:

; int __cdecl main()
main proc near

a= dword ptr -44h
b= dword ptr -24h

push    rdi
sub     rsp, 60h
mov     rdi, rsp
mov     ecx, 18h
mov     eax, 0CCCCCCCCh
rep stosd
mov     [rsp+68h+a], 0Ah
mov     [rsp+68h+b], 14h
mov     edx, [rsp+68h+b] ; b
mov     ecx, [rsp+68h+a] ; a
call    j_?_swap@@YAXHH@Z ; _swap(int,int)
mov     r8d, [rsp+68h+b]
mov     edx, [rsp+68h+a]
lea     rcx, aDD        ; "%d,%d\n"
call    cs:__imp_printf
lea     rdx, [rsp+68h+b] ; b
lea     rcx, [rsp+68h+a] ; a
call    j_?swap1@@YAXPEAH0@Z ; swap1(int *,int *)
mov     r8d, [rsp+68h+b]
mov     edx, [rsp+68h+a]
lea     rcx, aDD_0      ; "%d,%d\n"
call    cs:__imp_printf
lea     rdx, [rsp+68h+b] ; b
lea     rcx, [rsp+68h+a] ; a
call    j_?swap2@@YAXAEAH0@Z ; swap2(int &,int &)
mov     r8d, [rsp+68h+b]
mov     edx, [rsp+68h+a]
lea     rcx, aDD_1      ; "%d,%d\n"
call    cs:__imp_printf
xor     eax, eax
mov     edi, eax
mov     rcx, rsp        ; frame
lea     rdx, v          ; v
call    _RTC_CheckStackVars
mov     eax, edi
add     rsp, 60h
pop     rdi
retn
main endp


; void __cdecl _swap(int a, int b)
?_swap@@YAXHH@Z proc near

var_18= dword ptr -18h
arg_0= dword ptr  8
arg_8= dword ptr  10h
;win x64不超过4个参数用寄存器传参
;但是堆栈会保留并且会赋值
mov     [rsp+arg_8], edx
mov     [rsp+arg_0], ecx
push    rdi
sub     rsp, 10h
mov     rdi, rsp
mov     ecx, 4
mov     eax, 0CCCCCCCCh
rep stosd
mov     ecx, [rsp+18h+arg_0]
mov     eax, [rsp+18h+arg_0]
mov     [rsp+18h+var_18], eax
mov     eax, [rsp+18h+arg_8]
mov     [rsp+18h+arg_0], eax
mov     eax, [rsp+18h+var_18]
mov     [rsp+18h+arg_8], eax
add     rsp, 10h
pop     rdi
retn
?_swap@@YAXHH@Z endp

; void __cdecl swap1(int *a, int *b)
?swap1@@YAXPEAH0@Z proc near

var_18= dword ptr -18h
arg_0= qword ptr  8
arg_8= qword ptr  10h

mov     [rsp+arg_8], rdx
mov     [rsp+arg_0], rcx
push    rdi
sub     rsp, 10h
mov     rdi, rsp
mov     ecx, 4
mov     eax, 0CCCCCCCCh
rep stosd
mov     rcx, [rsp+18h+arg_0]
mov     rax, [rsp+18h+arg_0]
mov     eax, [rax]
mov     [rsp+18h+var_18], eax
mov     rax, [rsp+18h+arg_0]
mov     rcx, [rsp+18h+arg_8]
mov     ecx, [rcx]
mov     [rax], ecx
mov     rax, [rsp+18h+arg_8]
mov     ecx, [rsp+18h+var_18]
mov     [rax], ecx
add     rsp, 10h
pop     rdi
retn
?swap1@@YAXPEAH0@Z endp



; void __cdecl swap2(int *a, int *b)
?swap2@@YAXAEAH0@Z proc near
var_18= dword ptr -18h
arg_0= qword ptr  8
arg_8= qword ptr  10h

mov     [rsp+arg_8], rdx
mov     [rsp+arg_0], rcx
push    rdi
sub     rsp, 10h
mov     rdi, rsp
mov     ecx, 4
mov     eax, 0CCCCCCCCh
rep stosd
mov     rcx, [rsp+18h+arg_0]
mov     rax, [rsp+18h+arg_0]
mov     eax, [rax]
mov     [rsp+18h+var_18], eax
mov     rax, [rsp+18h+arg_0]
mov     rcx, [rsp+18h+arg_8]
mov     ecx, [rcx]
mov     [rax], ecx
mov     rax, [rsp+18h+arg_8]
mov     ecx, [rsp+18h+var_18]
mov     [rax], ecx
add     rsp, 10h
pop     rdi
retn
?swap2@@YAXAEAH0@Z endp

对比一下:

指针与引用对比。两者反汇编代码是一样的。

1.为何用非指针非引用传参函数无效?

因为是在栈上的参数交换的地址内的数,属于公用的,并不是去改变x,y地址内的数。输出x,y当然没有改变。

2.指针、引用为何能改变?

因为它们找到x,y地址,改变了地址内的内容。

 

 

posted @ 2014-05-08 17:18  乾卦  阅读(369)  评论(0编辑  收藏  举报