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、寄存器等资源,所以指针间接访问提高了代码的效率。