1. 调用函数,使用函数返回值的流程:函数的返回值是一开始是存储在函数栈中的,然后复制到寄存器;在其他地方调用函数,使用函数的返回值时,会把寄存器中的函数返回值复制到到函数栈中进行使用,共完成两次拷贝
int SumIntArray(int array[], int length){
int sum = 0;
for (int i = 0; i < length; ++i) {
sum += array[i];
}
return sum;
}
int main(){
int array[5]={0,1,2,3,4};
int b = SumIntArray(array, 5);
printf("%d", b);
return 0;
}
这个 demo 中,SumIntArray(array, 5) 的结果 sum 的值,就是先从函数栈拷贝到 eax 寄存器中,然后再从 eax 寄存器拷贝到变量 b 所在的函数栈地址中
之所以会发生两次拷贝,是因为指向函数栈的指针的值是变化的( [rbp-4] 的值是变化的 ),所以要将函数返回值暂存到寄存器中,等到要使用的时候再调用寄存器使用
2. 在 mingw 编译器下,通过 GDB 可以查看寄存器的值,这里查看 rbp 寄存器值的变化(我电脑只能查看 ebp 寄存器)
所以要用 eax 寄存器暂存一下函数的返回值,因为 ebp 值会变
3. 寄存器 EDX 和 RDX 的关系,RDX 的低32位就是 EDX,同样 EAX 是 RAX 的低32位,低32位清0的情况下,高32位也会清0,即 EDX 初始化等同 RDX 初始化
5. 结构体返回值:当函数返回值过大,一个寄存器存不下该怎么办?====> 使用多个寄存器进行存储
6. 将想返回的值,它的指针变量作为参数传入到函数中,避免发生两次拷贝,现在只发生了一次拷贝,从函数栈拷贝到寄存器中,没有后面那次寄存器拷贝至函数栈了
void SumIntArray2(int array[], int length, int *sum){
*sum = 0;
for (int i = 0; i < length; ++i) {
*sum += array[i];
}
}
7. 使用指针参数作为返回值的好处,
1)避免函数返回值带来的开销
2)实现函数多个返回值的目的
提问:
1. 关于5,结构体那边没太看懂汇编,尤其是赋值那一块
2. 关于6,这里真的是发生一次拷贝吗?虽然说 sum 的值被存储在了 rax 寄存器中,但是在 main 函数的使用中,不会将寄存器的值拷贝到函数栈中进行使用吗?原先的第二次拷贝就是为了使用才放到函数栈中的,尤其是在 main 函数中多添加一段 sum=sum+1 的代码,观察它的汇编代码:
如果这样,使用指针进行传参是否是一次拷贝,再者,指针传参减少了总程序的拷贝次数吗?