VC6对函数返回过程的优化(上)
VC6对函数返回过程的优化(上)
写了一天的计划,轻松一下脑筋,看看VC++6.0是怎么优化函数的返回值的过程。创建一个叫test的控制台项目。编译然后把反汇编的选项打开。
先作一个加法运算: c
= a + b
1: // test.cpp :
Defines the entry point for the console application.
2: //
3:
4: #include "stdafx.h"
5:
6: int test( int a, int b);
7:
8:
9: int main(int argc, char* argv[])
10: {
0040D3B0
push ebp
0040D3B1 mov
ebp,esp
0040D3B3 sub
esp,4Ch
0040D3B6 push ebx
0040D3B7 push esi
0040D3B8 push edi
0040D3B9 lea edi,[ebp-4Ch]
0040D3BC mov
ecx,13h
0040D3C1 mov
eax,0CCCCCCCCh
0040D3C6 rep stos dword ptr [edi]
11: int a, b, c;
12:
13: a = 0x11;
0040D3C8
mov dword ptr [ebp-4],11h
14: b = 0x30;
0040D3CF
mov dword ptr [ebp-8],30h
15:
16: c = test( a, b);
0040D3D6
mov eax,dword ptr [ebp-8] ;
取变量b的值
0040D3D9 push eax
; 压栈,变量是从右到左压栈
0040D3DA mov
ecx,dword ptr [ebp-4] ; 取变量b的值
0040D3DD push ecx
; 压栈
0040D3DE call
@ILT+0(test) (00401005)
0040D3E3 add esp,8
; 恢复栈
0040D3E6 mov dword
ptr [ebp-0Ch],eax
17:
18: return 0;
0040D3E9
xor eax,eax
19: }
0040D3EB
pop edi
0040D3EC pop esi
0040D3ED pop ebx
0040D3EE add
esp,4Ch
0040D3F1 cmp
ebp,esp
0040D3F3 call __chkesp
(0040d400)
0040D3F8 mov
esp,ebp
0040D3FA pop ebp
0040D3FB ret
20:
21:
22: int test( int a, int b)
23: {
00401050
push ebp
00401051 mov
ebp,esp
00401053 sub
esp,44h ;
00401056 push ebx
00401057 push esi
00401058 push edi
00401059 lea edi,[ebp-44h]
0040105C mov
ecx,11h
00401061 mov
eax,0CCCCCCCCh
00401066 rep stos dword ptr [edi] ;初始化局部变量空间
24: int c;
25: c = a + b;
00401068
mov eax,dword ptr [ebp+8]
0040106B add
eax,dword ptr [ebp+0Ch]
0040106E mov dword
ptr [ebp-4],eax
26: return c;
00401071
mov eax,dword ptr [ebp-4]
27: }
00401074
pop edi
00401075 pop esi
00401076 pop ebx
00401077 mov
esp,ebp
00401079 pop ebp
0040107A ret
在26行里面,函数的返回值被放到了EAX里面。好奇的人一定要问,如果返回值是一个结构怎么办?下一个,我们让返回值是一个复数结构(长度是两个32bits)。
1:
// test.cpp : Defines the entry point for the console application.
2: //
3:
4: #include "stdafx.h"
5:
6: struct complex{
7: int i; //real part
8: int j; //virtual part
9: };
10:
11: complex test( int a, int b);
12:
13:
14: int main(int argc, char* argv[])
15: {
0040D440
push ebp
0040D441 mov
ebp,esp
0040D443 sub
esp,58h
0040D446 push ebx
0040D447 push esi
0040D448 push edi
0040D449 lea edi,[ebp-58h]
0040D44C mov
ecx,16h
0040D451 mov
eax,0CCCCCCCCh
0040D456 rep stos dword ptr [edi]
16: int a, b;
17: struct complex c;
18:
19: a = 0x11;
0040D458
mov dword ptr [ebp-4],11h
20: b = 0x30;
0040D45F
mov dword ptr [ebp-8],30h
21:
22: c = test( a, b);
0040D466
mov eax,dword ptr [ebp-8]
0040D469 push eax
0040D46A mov
ecx,dword ptr [ebp-4]
0040D46D push ecx
0040D46E call
@ILT+10(test) (0040100f)
0040D473 add esp,8
0040D476 mov dword
ptr [ebp-18h],eax
0040D479 mov dword
ptr [ebp-14h],edx
0040D47C mov
edx,dword ptr [ebp-18h]
0040D47F mov dword
ptr [ebp-10h],edx
0040D482 mov
eax,dword ptr [ebp-14h]
0040D485 mov dword
ptr [ebp-0Ch],eax
23:
24: return 0;
0040D488
xor eax,eax
25: }
0040D48A
pop edi
0040D48B pop esi
0040D48C pop ebx
0040D48D add
esp,58h
0040D490 cmp
ebp,esp
0040D492 call __chkesp
(0040d400)
0040D497 mov
esp,ebp
0040D499 pop ebp
0040D49A ret
28:
struct complex test( int a, int b)
29: {
00401050
push ebp
00401051 mov
ebp,esp
00401053 sub
esp,48h
00401056 push ebx
00401057 push esi
00401058 push edi
00401059 lea edi,[ebp-48h]
0040105C mov
ecx,12h
00401061 mov
eax,0CCCCCCCCh
00401066 rep stos dword ptr [edi]
30: struct complex c;
31: c.i = a;
00401068
mov eax,dword ptr [ebp+8]
0040106B mov dword
ptr [ebp-8],eax
32: c.j = b;
0040106E
mov ecx,dword ptr [ebp+0Ch]
00401071 mov dword
ptr [ebp-4],ecx
33:
34: return c;
00401074
mov eax,dword ptr [ebp-8]
00401077 mov
edx,dword ptr [ebp-4]
35: }
0040107A
pop edi
0040107B pop esi
0040107C pop ebx
0040107D mov
esp,ebp
0040107F pop ebp
00401080 ret
注意看34行,编译器够聪明,用EAX和EDX来返回复数c的实部和虚部。嘿嘿,我就不相信你x86的CISC处理器的寄存器能多过RISC处理器,返回值是更多个32bits又到哪里去找那么多寄存器呢?电动力学的四个方程都可以把变量表达成(x,y,z,t)这样的向量,我让子函数返回这样一个向量。(待续)
分类
Software

发表评论