【汇编】C++ 函数调用之——有参无返回调用(传指针)

  1. 【汇编】C++ 函数调用之——有参无返回调用(传值)

传地址调用函数顾名思义,就是向被调函数传递的是一个地址值,而不是数据内容,这个地址通常是一个32位无符号整数,表示为十六进制就是形如:0x???? ????,在实际内存中是以(DWORD)形式存放 ,这就是指针类型在内存中通常占用4字节的原因。

有源代码:

1
2
3
4
5
6
7
8
9
10
11
void func(int *b){
*b=10;
}

int main(int argc,char *argv[])
{
//call func
int a;
func(&a);
return 0;
}

这段代码就是通过func函数修改main函数的一个局部变量a。

main函数中对应的汇编码如下所示:

1
2
3
4
5
6
7
8
9
10
//call func
int a;
func(&a);
00911438 lea eax,[ebp-0Ch]
0091143B push eax
0091143C call 009111D1
00911441 add esp,4
//可以看到,传指针时,有一个lea指令,该指令是将局部变量a的地址也就是ebp-0ch传送给寄存器eax
//然后将eax压栈,换句话说压栈的内容是&a(ebp-0ch)
//后续操作和之前介绍的传值调用一致

为了更直观一些,我们在内存窗口查看这个地址放在哪儿了。然后由这个地址找到a所在内存单元,看是不是0xCCCCCCCC(请参考)

&a=0x0109FEE0

PUSH &a

再看看func函数:

1
2
3
4
5
*b=10;
009113EE mov eax,dword ptr [ebp+8]
//从栈底偏移+8处取出调用时push的&a,从内存中也可以看出正好是放在那里的
009113F1 mov dword ptr [eax],0Ah
//注意这里eax存的是&a,作为地址然后找到对应的内存单元,向里面传送10,就是实现了*b=10

内存中是怎么样的呢?

0x0109FEE0处:

可以看到确实变成了0a

和传值调用唯一的不同就是参数压栈时压的是地址而已。

如果需要向函数传一个对象,而这个对象占用很大的一块内存,如果使用传值方式,则需要在被调函数栈底下面(参数表)push一个对象,相当于完全拷贝这个对象,占用同样的内存空间。

而如果使用传指针,那么仅仅需要push一个4字节的地址值而已,对象没有发生拷贝,大大节省了内存和时间。这就是使用指针的高效处。

0%