原来一直没有试验过用结构体作为参数传递和返回, 一直说结构体作为参数传递很慢撒的, 所以也没有 去关心过结构体在内存中的存储形式, 这下上课讲到这个. 不得不关注下这个结构体的具体形式了..

以一个最简单的结构体传参研究下.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>

typedef struct tagNode {
	int i, j, k;
}NODE, *PNODE;

NODE function( PNODE pStNode, NODE StNode ) {
	return 	*pStNode;
}

int main( int argc, char* argv[] ) {
	NODE StNode;
	NODE StNode2;

	StNode.i = 10;
	StNode.j = 20;
	StNode.k = 30;

	StNode2 = function( &StNode, StNode );
	return 0;
}

结构作为参数传递的堆栈结构, 结构体在堆栈中保存的时候. 从低地址保存结构的低位. 比如上面声明的结构, 变量i存放在[ebp-0ch]..减得比较多得地方. 和因为堆栈是往下增长的, 所以 [ebp-0c]是最低地址, [ebp-8]是j的地址, [ebp-4]是k的地址..

在传递参数的时候, 如果以结构直接传递的那么在堆栈中的结构也是首先声明的变量放在低地址.. 这个和我们一般传递变量的习惯也是有区别的.

如果在参数返回有结构体的时候, 在调用的时候就会给其留出空间, 放在第一个参数中. 以便给结构体存放. 然后结构体指针在eax中返回..在Debug版本中的返回值中间还经过了一段临时内存的 存放, 这个我想在Release中就没有了,不过套路还是一样. 就是在eax中返回指向结构的首地址(最低地址).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
;============================================================================
;NODE function( PNODE pStNode, NODE StNode )
 push        ebp
 mov         ebp,esp
 sub         esp,40h
 push        ebx
 push        esi
 push        edi				;框架结构

 mov         eax,dword ptr [ebp+0Ch]		;pStNode
 mov         ecx,dword ptr [ebp+8]		;调用函数时留出的空间
 mov         edx,dword ptr [eax]		;pStNode->i
 mov         dword ptr [ecx],edx		;StTempNode.i
 mov         edx,dword ptr [eax+4]		;pStNode->j
 mov         dword ptr [ecx+4],edx		;StTempNode.j
 mov         eax,dword ptr [eax+8]		;pStNode->k
 mov         dword ptr [ecx+8],eax		;StTempNode.k
 mov         eax,dword ptr [ebp+8]		;return pStNode

 pop         edi				;释放框架
 pop         esi
 pop         ebx
 mov         esp,ebp
 pop         ebp
 ret
;============================================================================
;StNode2 = function( &StNode, StNode );

sub         esp,0Ch
mov         eax,esp				;eax-->StNode
mov         ecx,dword ptr [ebp-0Ch]		;i
mov         dword ptr [eax],ecx			;StNode.i
mov         edx,dword ptr [ebp-8]		;j
mov         dword ptr [eax+4],edx		;StNode.j
mov         ecx,dword ptr [ebp-4]		;k
mov         dword ptr [eax+8],ecx		;StNode.k

lea         edx,[ebp-0Ch]			;push *StNode
push        edx

lea         eax,[ebp-5Ch]
push        eax					;用于返回

call        @ILT+5(function) (0040100a)
add         esp,14h				;平衡堆栈

mov         ecx,dword ptr [eax]			;i
mov         dword ptr [ebp-24h],ecx		;StTempNode.i
mov         edx,dword ptr [eax+4]		;j
mov         dword ptr [ebp-20h],edx		;StTempNode.j
mov         eax,dword ptr [eax+8]		;k
mov         dword ptr [ebp-1Ch],eax		;StTempNode.k

mov         ecx,dword ptr [ebp-24h]		;StTempNode.i
mov         dword ptr [ebp-18h],ecx		;StNode2.i
mov         edx,dword ptr [ebp-20h]		;StTempNode.j
mov         dword ptr [ebp-14h],edx		;StNode2.j
mov         eax,dword ptr [ebp-1Ch]		;StTempNode.k
mov         dword ptr [ebp-10h],eax		;StNode2.k