函数的返回值保存在内存的什么区域呢??

 2024-01-07 01:00:46  阅读 0

1. 如果结构体大小不超过4字节,则仍然使用EAX寄存器来传输返回值

2、当结构体超过4字节但不等于8字节时,调用者会先在栈上分配一块可以容纳该结构体的临时内存块,然后在传递函数参数后,使用该临时内存的首地址block as 隐式第一个参数最后入栈(因为入栈顺序是从右到左),后续动作和之前一样。 当被调用函数返回时,它会通过第一个隐式参数寻址临时内存块并将返回值复制到其中,然后将保存返回值内容的临时内存块的首地址存储到eax寄存器中。

3、当结构体大小正好是8字节时,编译器不再在栈上分配内存,而是直接使用EAX和EDX两个寄存器来传输返回值。 EAX 存储数据的低 4 个字节,EDX 存储数据的高 4 个字。 截面数据。

当定义一个函数时,它必须有它的返回类型。 返回类型可以是数字(指针是代表地址的数值)或void。 该函数只能返回一个值,数值形式可以是 4 字节整数、浮点数、8 字节 long long 或结构体类型。 虽然都是返回值,但是返回机制不同。

函数的局部变量是在栈中定义的,是后进先出(LIFO)的。 局部变量所在栈的高地址在栈底,低地址在栈顶。 从main开始,申请变量时,栈顶指针向上移动,进入局部变量。 局部变量的应用与main函数中相同。 子函数执行完毕后,栈顶指针向下移动到进入局部变量时的位置。 子函数回收所有已申请的局部变量空间。 因此,如果函数需要子函数中的某个值,则可以通过返回数据来获取(使用指针间接访问变量时不需要返回)。

1)讨论整数、浮点类型和指针等4字节值。

以下函数是一个示例:

int add(int x,int y){

int z=x+y;

z;

int main(){

int sum=add(3,4);

0;

该函数返回部分汇编代码:

z;

8B 45 F8 mov eax,dword ptr [z]

在这一段中,可以看到z中计算出来的数据被移动到eax寄存器中,eax寄存器将值带到调用函数的函数变量中。

返回这些类型时,系统将函数要返回的值移入寄存器,栈顶指针下移,栈内所有局部变量死亡,寄存器中的数据返回给要返回的变量。由调用该函数的函数接收。

2)讨论诸如8字节大小之类的值。

在32位编译环境下,eax寄存器一次只能接受和传输4字节的数据,8字节的大小显然无法一次性完全获得。

代码就是将上面的int改为long long类型。

函数返回部分的汇编代码:

z;

8B 45 F4 mov eax,dword ptr [z]

8B 55 F8 mov edx,dword ptr [ebp-8]

该函数的返回机制与 4 字节函数类似,只是使用两个寄存器来返回值。 long 长字节被分成两部分并移至 eax 和 edx 寄存器。 函数值通过这两个寄存器返回。 。

3)返回结构体类型的数据

一个结构体变量可以包含多个不同的数据变量,其大小很容易超过8个字节。 依靠多个寄存器将值返回给调用函数是非常不现实的。

功能示例:

{

​int 数字;

字符名称[19];

炭性;

浮动分数;

};

测试(){

斯图;

(stu.name,"");

Stu.num=1001;

stu.score=99.9;

Stu.sex='M';

斯图;

int main(){

苏;

苏=测试();

0;

该函数的返回类型是结构体类型,该类型的大小为28字节。

函数返回部分的汇编代码:

斯图;

B9 07 00 00 00 mov ecx,7

8D 75 DC lea esi,[stu]

8B 7D 08 mov edi,dword ptr [ebp+8]

F3 A5 代表 movs dword ptr es:[edi],dword ptr [esi]

斯图;

8B 45 08 mov eax,dword ptr [ebp+8]

在进入子函数之前,系统会在堆栈上为该函数留下一段内存。 当函数返回此类数据时,寄存器首先将数据移动到段空间,然后子函数中的数据就消亡了。 Space 将值返回到调用函数的变量中。 这种方式成本比较高,消耗空间,而且在复制和传输时还占用CPU、寄存器等资源,所以指针间接访问提高了代码的效率。

如本站内容信息有侵犯到您的权益请联系我们删除,谢谢!!


Copyright © 2020 All Rights Reserved 京ICP5741267-1号 统计代码