程序调用过程和堆栈的关系,为什么要传地址而不传值

bug.c

void swap(int a, int b)
{
    int c;
    c = a;
    a = b;
    b = c;
    
}

int main()
{
    int a,b;
    a = 16;
    b = 32;
    swap(a, b);
    return (a-b);
}

使用gdb调试,main函数反汇编的代码

(gdb) x /20i $pc
=> 0x40135c :  movl   $0x10,0x1c(%esp)
   0x401364 :  movl   $0x20,0x18(%esp)
   0x40136c :  mov    0x18(%esp),%eax
   0x401370 :  mov    %eax,0x4(%esp)
   0x401374 :  mov    0x1c(%esp),%eax
   0x401378 :  mov    %eax,(%esp)
   0x40137b :  call   0x401334 
   0x401380 :  mov    0x18(%esp),%eax
   0x401384 :  mov    0x1c(%esp),%edx
   0x401388 :  mov    %edx,%ecx
   0x40138a :  sub    %eax,%ecx
   0x40138c :  mov    %ecx,%eax
   0x40138e :  leave
   0x40138f :  ret

swap函数的反汇编代码

(gdb) x /20i 0x401334
   0x401334 :     push   %ebp
   0x401335 :   mov    %esp,%ebp
   0x401337 :   sub    $0x10,%esp
   0x40133a :   mov    0x8(%ebp),%eax
   0x40133d :   mov    %eax,-0x4(%ebp)
   0x401340 :  mov    0xc(%ebp),%eax
   0x401343 :  mov    %eax,0x8(%ebp)
   0x401346 :  mov    -0x4(%ebp),%eax
   0x401349 :  mov    %eax,0xc(%ebp)
   0x40134c :  leave
   0x40134d :  ret 

在执行到call swap函数之前,main函数的esp和ebp的值,以及栈中内容的情况

main函数的sp和ebp
(gdb) info r esp
esp            0x28ff00 0x28ff00
(gdb) info r ebp
ebp            0x28ff28 0x28ff28    

main函数栈中的内容,esp是栈顶

0x28ff00:       0x10    0x00    0x00    0x00    0x20    0x00    0x00    0x00

从这里看,esp存放的是a的值,esp+4存放的是b的值,swap函数进行操作的也是这块内存.
 那么a,b真正的地址在哪?

main函数里面
(gdb) p /x &a
$1 = 0x28ff1c
(gdb) p /x &b
$2 = 0x28ff18
swap函数里面
(gdb) p /x &a
$2 = 0x28ff00
(gdb) p /x &b
$3 = 0x28ff04

可见swap函数操作的main函数的a,b在栈上的备份,执行完swap函数返回后,这部分栈就被废弃了,而a,b真正所在地的值并没有得到更改.

而swap函数的堆栈在哪?
从0x28fee8到0x28ff00(一个保存的ebp,三个形参,总计16字节),函数的返回地址是属于main函数的堆栈,从0x28ff00-04,这是swap的返回地址刚好是call swap的下一条指令

(gdb) x /32bx 0x28fee8
0x28fee8:       0x08    0xff    0x28    0x00    0xc4    0xff    0x28    0x00
0x28fef0:       0xd5    0x8c    0x47    0x77    0xd2    0x10    0x70    0x9a
0x28fef8:       0x28    0xff    0x28    0x00    0x80    0x13    0x40    0x00
0x28ff00:       0x10    0x00    0x00    0x00    0x20    0x00    0x00    0x00
swap函数的返回地址
 0x401380 :  mov    0x18(%esp),%eax

你可能感兴趣的:(程序调用过程和堆栈的关系,为什么要传地址而不传值)