从汇编代码分析(一级)指针形参

用于测试的C++源码:

int* f(int *a)
{
    *a=10;
    a=0;
    return a;
}
int main(int argc, char **argv)
{
    int a = 1, *p = &a;
    f(p);
}

MS Windows x64, 汇编代码:

Dump of assembler code for function f(int*):
   0x0000000000401550 <+0>:    push   rbp
   0x0000000000401551 <+1>:    mov    rbp,rsp
   0x0000000000401554 <+4>:    mov    QWORD PTR [rbp+0x10],rcx    ;分配新的地址空间[rbp+0x10]用于保存p=&a,a地址值
=> 0x0000000000401558 <+8>:    mov    rax,QWORD PTR [rbp+0x10]    ;a地址值传给rax
   0x000000000040155c <+12>:    mov    DWORD PTR [rax],0xa       ;修改a地址处的内存值 *p=10,注:此处mian函数中变量a值被修改。
   0x0000000000401562 <+18>:    mov    QWORD PTR [rbp+0x10],0x0    ;修改新的内存地址[rbp+0x10]的值为0
   0x000000000040156a <+26>:    mov    rax,QWORD PTR [rbp+0x10]    ;返回新地址空间[rbp+0x10]的值,f(p)=rax=0。
   0x000000000040156e <+30>:    pop    rbp
   0x000000000040156f <+31>:    ret    
End of assembler dump.
Dump of assembler code for function main(int, char**):           ;main函数被库函数__tmainCRTStartup调用。__tmainCRTStartup被WinMainCRTStartup或WinMainCRTStartup,mainCRTStartup(用于控制台应用程序)调用
   0x0000000000401570 <+0>:    push   rbp                     ;外部函数的rbp入栈
   0x0000000000401571 <+1>:    mov    rbp,rsp
   0x0000000000401574 <+4>:    sub    rsp,0x30                ;开辟main函数栈空间:0x30
   0x0000000000401578 <+8>:    mov    DWORD PTR [rbp+0x10],ecx       ;main函数参数1:argc
   0x000000000040157b <+11>:    mov    QWORD PTR [rbp+0x18],rdx      ;main函数参数2:argv
   0x000000000040157f <+15>:    call   0x4016e0 <__main>          ;_main检测初始化是否完成。若initialized不为0,则retrun eip;若initialized为0,则设为initialized=1,然后call __do_global_ctors
   0x0000000000401584 <+20>:    mov    DWORD PTR [rbp-0xc],0x1       ;a=1,a地址:[rbp-0xc],类型int
   0x000000000040158b <+27>:    lea    rax,[rbp-0xc]             ;获取a变量地址
   0x000000000040158f <+31>:    mov    QWORD PTR [rbp-0x8],rax       ;p=&a,把a变量地址传输给指针变量p;p地址[rbp-0x8]
   0x0000000000401593 <+35>:    mov    rax,QWORD PTR [rbp-0x8]       ;获取p变量值,即变量a的地址。
   0x0000000000401597 <+39>:    mov    rcx,rax                ;f(int*)参数保存在rcx中,rcx=p=&a
   0x000000000040159a <+42>:    call   0x401550 <f(int*)>          ;call f(int*)
   0x000000000040159f <+47>:    mov    eax,0x0                ;main函数返回值eax=0.
   0x00000000004015a4 <+52>:    add    rsp,0x30                ;回收main函数栈空间
   0x00000000004015a8 <+56>:    pop    rbp                 
   0x00000000004015a9 <+57>:    ret    
End of assembler dump.

 结论:

f(int*)执行后:

f(int* )函数中*a=10,改变了main函数中变量a的值,即改变了指针p所指对象的值

f(int*)函数中a=0,对main函数中a变量无影响,改变了指针p的局部拷贝对象,实参未改变

 

posted @ 2023-08-11 23:08  mibrcogu  阅读(48)  评论(0)    收藏  举报