代码如下:
#include <cstdio> struct node { int a; int b; int c; int d; int f; int g; int h; int i; }; struct node RetStruct() { struct node stNode; stNode.a = 1; stNode.b = 2; stNode.c = 3; stNode.d = 4; stNode.f = 5; stNode.g = 6; stNode.h = 7; stNode.i = 8; return stNode; } int main() { struct node stRet = RetStruct(); printf("%d, %d", stRet.a, stRet.b); return 0; }
main反汇编后为:
从(0041144D ~ 0041145A)中看出,当返回的局部变量无法用寄存器保存时,返回指向局部变量的地址于EAX,并接下复制局部变量于临时变量(0041145A)。
最后把临时变量的数据复制到 stRet 中(0041145C ~ 0041146A)。
看下返回的局部变量可以用寄存器容纳下时
#include <cstdio>
struct node { int a; int b; };
struct node RetStruct() { struct node stNode; stNode.a = 1; stNode.b = 2; return stNode; } int main() {
struct node stRet = RetStruct(); printf("%d, %d", stRet.a, stRet.b); return 0; }
main反汇编后,如下:
用EAX返回node.a == 1再用 EDX返回node.b == 2 (00411443 ~ 00411449),最后才复制到stRet中(0041144F~0041145E)
总结:
足够用寄存器保存时寄存器保存,不足时,EAX保存临时变量地址返回:
1)先从调用函数开劈1个结构体大小的临时内存,把这个临时结构体地址(设为RetAddress)用EAX而且入栈,以传递给被调用函数RetStruct()中,这个临时结构体保存被调用函数中的要返回的局部结构体的值。
2)被调用函数在返回前把要返回的局部变量结构体的值复制到RetAddress结构体中,然后把RetAddress的地址保存于EAX中,并且被调用函数弹栈返回
3)被调用函数返回后,立即复制RetAddress结构体的值于另一个结构体的地址中,设为Address(注:这个地址不是RetAddress)
4)再次复制Adress的值保存于MAIN的局部变量stRet中