WEB开发网
开发学院软件开发C语言 c#编程指南(十四) 平台调用P-INVOKE完全掌握, 反汇... 阅读

c#编程指南(十四) 平台调用P-INVOKE完全掌握, 反汇编细解结构体作为返回值

 2010-09-30 22:46:03 来源:WEB开发网   
核心提示:这篇解决上篇那个结构体作为返回值的问题,我们结合反汇编来探索这里面的秘密,c#编程指南(十四) 平台调用P-INVOKE完全掌握, 反汇编细解结构体作为返回值,如何反汇编?方法如下:在C++函数内下断点,调试到断点断下,无法正常通EAX,EDX返回,所以编译器把函数编译成带输入参数的函数,右键菜单,选择"反汇

这篇解决上篇那个结构体作为返回值的问题。我们结合反汇编来探索这里面的秘密。如何反汇编?

方法如下:在C++函数内下断点,调试到断点断下,右键菜单,选择"反汇编",反汇编是VS自带功能。

下面是几个简单的类:

 1 struct Test1
 2 {
 3   int Count1;
 4 };
 5 
 6  struct Test2
 7 {
 8   int Count1;
 9   int Count2;
10 };
11 
12  struct Test3
13 {
14   int Count1;
15   int Count2;
16   int Count3;
17 };

分别用上面的方法来逐个分析汇编:汇编里有我详细的注释:

 1 
 2 当返回Test1的时候:汇编如下:
 3 函数内:
 4  ;----------------------------GetTest函数内-------------------------------------------------
 5    _test.Count = 3333;
 6  00411B0E mov     dword ptr [_test (4174C4h)],0D05h 
 7   return _test;
 8  00411B18 mov     eax,dword ptr [_test (4174C4h)] ; //把返回值放到EAX寄存器
 9 ;---------------------------主函数调用GetTest----------------------------------------------
10    Test test = GetTest();
11  004135FE call    GetTest (4110E1h) 
12  00413603 mov     dword ptr [ebp-0D4h],eax ;//将返回值存储在栈中分配的变量中。
13 ;---------------------------------------------------------------------------------------------------
14 
15 看来虽然Test1是结构体,但是由于就占4个字节,所以通过EAX正常返回。
16 
17 
18 看下Test2的反汇编:
19 ;----------------------------GetTest函数内-------------------------------------------------
20   _test.Count = 3333;
21 00411B0E mov     dword ptr [_test (4174C4h)],0D05h 
22   _test.Count2 = 4444;
23 00411B18 mov     dword ptr [_test+4 (4174C8h)],115Ch 
24   return _test;
25 00411B22 mov     eax,dword ptr [_test (4174C4h)] ;返回值通过EAX,EDX返回
26 00411B27 mov     edx,dword ptr [_test+4 (4174C8h)] 
27 ;---------------------------主函数调用GetTest----------------------------------------------
28   Test test = GetTest();
29 004135FE call    GetTest (4110E1h) 
30 00413603 mov     dword ptr [ebp-0DCh],eax ;返回值存入栈中变量
31 00413609 mov     dword ptr [ebp-0D8h],edx 
32 ;---------------------------------------------------------------------------------------------------
33 
34 虽然Test2占8个字节,但是编译器通过组合EAX,EDX可以正确返回。
35 
36 
37 看下Test3的反汇编:
38 ;----------------------------GetTest函数内-------------------------------------------------
39 00411470 push    ebp 
40 00411471 mov     ebp,esp ;构建栈帧
41 
42 00411473 sub     esp,0C0h ;分配局部变量
43 
44 00411479 push    ebx 
45 0041147A push    esi 
46 0041147B push    edi ;保存寄存器环境
47 
48 0041147C lea     edi,[ebp-0C0h] 
49 00411482 mov     ecx,30h 
50 00411487 mov     eax,0CCCCCCCCh 
51 0041148C rep stos  dword ptr es:[edi] ;设置trap area.
52 
53   _test.Count1 = 3333;
54 0041148E mov     dword ptr [_test (417140h)],0D05h 
55   _test.Count2 = 4444;
56 00411498 mov     dword ptr [_test+4 (417144h)],115Ch 
57   _test.Count3 = 5555;
58 004114A2 mov     dword ptr [_test+8 (417148h)],15B3h 
59 
60 
61   return _test;
62 004114AC mov     eax,dword ptr [ebp+8] ;得到第一个参数,注意__stdcall从右向左压栈.
63 
64 004114AF mov     ecx,dword ptr [_test (417140h)] 
65 004114B5 mov     dword ptr [eax],ecx ;参数是一个指针,写入第一个成员;
66 004114B7 mov     edx,dword ptr [_test+4 (417144h)] 
67 004114BD mov     dword ptr [eax+4],edx ;参数是一个指针,写入第二个成员;
68 004114C0 mov     ecx,dword ptr [_test+8 (417148h)] 
69 004114C6 mov     dword ptr [eax+8],ecx ;参数是一个指针,写入第三个成员;
70 004114C9 mov     eax,dword ptr [ebp+8] 
71 ;---------------------------主函数调用GetTest----------------------------------------------
72 Test test = GetTest();
73 004113BE lea     eax,[ebp-0E4h] 
74 004113C4 push    eax ;压栈参数
75 004113C5 call    GetTest (4110E1h) 
76 004113CA add     esp,4 ;回收栈帧
77 
78 004113CD mov     ecx,dword ptr [eax] ;返回参数。
79 
80 004113CF mov     dword ptr [ebp-0F8h],ecx ; 写入局部变量test
81 004113D5 mov     edx,dword ptr [eax+4] 
82 004113D8 mov     dword ptr [ebp-0F4h],edx 
83 004113DE mov     eax,dword ptr [eax+8] 
84 004113E1 mov     dword ptr [ebp-0F0h],eax 
85 004113E7 mov     ecx,dword ptr [ebp-0F8h] 
86 004113ED mov     dword ptr [test],ecx 
87 004113F0 mov     edx,dword ptr [ebp-0F4h] 
88 004113F6 mov     dword ptr [ebp-0Ch],edx 
89 004113F9 mov     eax,dword ptr [ebp-0F0h] 
90 004113FF mov     dword ptr [ebp-8],eax 
91   return 0;
92 00411402 xor     eax,eax 
93 ;---------------------------------------------------------------------------------------------------
94 
95 Test3占12字节,无法正常通EAX,EDX返回,所以编译器把函数编译成带输入参数的函数,
96 就好像Test test = GetTest(&test);一样。

1 2  下一页

Tags:编程 指南 十四

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接