• 指针与引用


    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
    ",x,y);
        swap1(&x,&y);
        printf("%d,%d
    ",x,y);
        swap2(x,y);
        printf("%d,%d
    ",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
    ",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
    ",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
    ",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
    "
    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
    "
    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
    "
    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地址,改变了地址内的内容。

  • 相关阅读:
    Table Scan, Index Scan, Index Seek
    Ndo v3.1发布了!
    手动建立强类型DataSet
    <.NET分布式应用程序开发>读书笔记 第十章:Q&A
    HQL语法大全
    IT人才最容易犯的几个错误
    在线查询Windows API
    ODP.NET和System.Data.OracleClient的一些不同
    给PDF文件添加链接和书签
    cegui0.6.0的下载、安装、配置及samples浏览
  • 原文地址:https://www.cnblogs.com/qiangua/p/3716622.html
Copyright © 2020-2023  润新知