分类目录

展开|收起

看你喜欢

(1) (1) (42) (1) (1) (1) (16) (2) (1) (1) (4) (1) (2) (7) (4) (1) (1) (1) (1) (3) (1) (5) (1) (1) (1) (1) (1) (2) (1) (4) (4) (3) (1) (1) (2) (1) (37) (2) (1) (5) (3) (1) (4) (1) (1) (11) (3) (1) (9) (3) (1) (23) (2) (1) (2) (1) (1) (1) (1)

最新精华

函数调用汇编分析【3】- 实例分析4(结构作为参数和返回值,返回值长度小于等于8)

3.4 结构作为参数和返回值(返回值长度小于等于8)

(1)源程序

#include <stdio.h>
typedef struct T_test
{
  char x;
  int y;
}T_test;

T_test add(T_test c , T_test d)
{
    T_test e;
    e.x=c.x+d.x;
    e.y=c.y+d.y;
  
    return e;
}

void main()
{
    T_test a = {1,2};
    T_test b = {3,4};

    T_test c;

    c=add(a,b);

    while (1)
    {
    }
}

(2)汇编代码

1:    #include <stdio.h>
2:    typedef struct T_test
3:    {
4:      char x;
5:      int y;
6:    }T_test;
7:
8:    T_test add(T_test c , T_test d)
9:    {
0040B650   push        ebp            
0040B651   mov         ebp,esp
0040B653   sub         esp,48h
0040B656   push        ebx
0040B657   push        esi
0040B658   push        edi
0040B659   lea         edi,[ebp-48h]
0040B65C   mov         ecx,12h
0040B661   mov         eax,0CCCCCCCCh
0040B666   rep stos    dword ptr [edi]
10:       T_test e;
11:       e.x=c.x+d.x;
0040B668   movsx       eax,byte ptr [ebp+8]     // 取c.x
0040B66C   movsx       ecx,byte ptr [ebp+10h]   // 取d.x
0040B670   add         eax,ecx                  // c.x+d.x
0040B672   mov         byte ptr [ebp-8],al      // e.x=c.x+d.x
12:       e.y=c.y+d.y;
0040B675   mov         edx,dword ptr [ebp+0Ch]  // 参见上面
0040B678   add         edx,dword ptr [ebp+14h]
0040B67B   mov         dword ptr [ebp-4],edx
13:
14:       return e;
0040B67E   mov         eax,dword ptr [ebp-8]   // eax=e.x
0040B681   mov         edx,dword ptr [ebp-4]   // dx=e.y
                                            返回值是8字节时,
返回值通过edx:eax返回
15:   }
0040B684   pop         edi
0040B685   pop         esi
0040B686   pop         ebx
0040B687   mov         esp,ebp
0040B689   pop         ebp
0040B68A   ret

16:
17:
18:   void main()
19:   {
0040B530   push        ebp
0040B531   mov         ebp,esp
0040B533   sub         esp,60h
0040B536   push        ebx
0040B537   push        esi
0040B538   push        edi
0040B539   lea         edi,[ebp-60h]
0040B53C   mov         ecx,18h
0040B541   mov         eax,0CCCCCCCCh
0040B546   rep stos    dword ptr [edi]
20:       T_test a = {1,2};
0040B548   mov         byte ptr [ebp-8],1   // 栈中保存a.x,在低地址
0040B54C   mov         dword ptr [ebp-4],2  // 栈中保存a.y
21:       T_test b = {3,4};
0040B553   mov         byte ptr [ebp-10h],3  // 栈中保存b.x
0040B557   mov         dword ptr [ebp-0Ch],4 // 栈中保存b.y
22:
23:       T_test c;
24:
25:       c=add(a,b);
0040B55E   mov         eax,dword ptr [ebp-0Ch]    
0040B561   push        eax                       // b.y的值入栈
0040B562   mov         ecx,dword ptr [ebp-10h]   
0040B565   push        ecx           // b.x的值入栈, 即栈中有一个b结构的副本
0040B566   mov         edx,dword ptr [ebp-4]
0040B569   push        edx                      // a.x的值入栈
0040B56A   mov         eax,dword ptr [ebp-8]
0040B56D   push        eax                      // a.y的值入栈
0040B56E   call        @ILT+30(add) (00401023)   // 调用add
0040B573   add         esp,10h                   // 调整堆栈
0040B576   mov         dword ptr [ebp-20h],eax   // 从eax取返回值的低32位,
                                                 保存到一个临时的地方temp
0040B579   mov         dword ptr [ebp-1Ch],edx   // 从edx取返回值的高32位,
                                                 保存到一个临时的地方temp
0040B57C   mov         ecx,dword ptr [ebp-20h]   
0040B57F   mov         dword ptr [ebp-18h],ecx
0040B582   mov         edx,dword ptr [ebp-1Ch]
0040B585   mov         dword ptr [ebp-14h],edx   // c=temp
26:
27:       while (1)
0040B588   mov         eax,1
0040B58D   test        eax,eax
0040B58F   je          main+63h (0040b593)
28:       {
29:       }
0040B591   jmp         main+58h (0040b588)
30:   }
0040B593   pop         edi
0040B594   pop         esi
0040B595   pop         ebx
0040B596   add         esp,60h
0040B599   cmp         ebp,esp
0040B59B   call        __chkesp (004010e0)
0040B5A0   mov         esp,ebp
0040B5A2   pop         ebp
0040B5A3   ret

说明:add()函数返回后,把edx:eax保存的返回值保存到堆栈的一个临时存放点[ebp-20h](相当于一个局部临时变量),这个地点的地址不是随便定的。

structure-para-1

(3)小结

可以看出,add函数函数返回时是把返回值放到EDX:EAX, 但不是直接赋给变量c,而是先赋给一个栈中的临时变量空间,然后再把这个临时变量赋给c。如果直接写成add(a,b);而不处理返回值,也有这个拷贝到temp的过程。比较怪异吧,参见下一个例子的分析。

  打分:5.0/5 (共3人投票)
(浏览总计: 59 次)
Add Comment Register



发表回复

  

  

  

您可以使用这些HTML标签

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>