C函数调用过程及汇编分析

来源:互联网 发布:mac os 升级 黑苹果 编辑:程序博客网 时间:2024/05/21 11:15

C代码:
int fun(int para)
{
    int a=0;
    return 0;
}

void main()
{
    fun(1);
}

汇编代码:

1:
2:
3:      int fun(int para)
4:      {
0040B810     push          ebp                                    ;保护寄存器ebp
0040B811     mov           ebp,esp                             ;此时ebp=esp;此后ebp一般不变
0040B813     sub           esp,44h                              ;44即为40Bytes间隔空间+fun内部变量占有空间,此时fun仅定义一int型变量a,故为4Bytes
0040B816     push          ebx                                      ;保护ebx
0040B817     push          esi                                       ;保护esi
0040B818     push          edi                                       ;保护edi


0040B819     lea           edi,[ebp-44h]                        ;以下四条代码将44Bytes空间置为0CCCCCCCCh
0040B81C     mov           ecx,11h
0040B821     mov           eax,0CCCCCCCCh
0040B826     rep stos      dword ptr [edi]

;以下为自己写的代码

5:        int a=0;
0040B828     mov           dword ptr [ebp-4],0
6:
7:
8:        return 1;
0040B82F     mov           eax,1                                   ;返回值被放入eax
9:      }
0040B831     pop           edi
0040B832     pop           esi
0040B833     pop           ebx
0040B834     mov           esp,ebp
0040B836     pop           ebp
0040B837     ret

10:
11:     void main()
12:     {
0040B790     push          ebp
0040B791     mov           ebp,esp
0040B793     sub           esp,40h
0040B796     push          ebx
0040B797     push          esi
0040B798     push          edi
0040B799     lea           edi,[ebp-40h]
0040B79C     mov           ecx,10h
0040B7A1     mov           eax,0CCCCCCCCh
0040B7A6     rep stos      dword ptr [edi]
13:
14:       fun(1);
0040B7A8     push          1                                                ;参数入栈
0040B7AA     call          @ILT+25(fun) (0040101e)
0040B7AF     add           esp,4                                         ;等效于参数出栈,恢复esp。(此时参数为1 个int型数据,占4Bytes)
15:
16:
17:     }
0040B7B2     pop           edi
0040B7B3     pop           esi
0040B7B4     pop           ebx
0040B7B5     add           esp,40h
0040B7B8     cmp           ebp,esp
0040B7BA     call          __chkesp (004010a0)
0040B7BF     mov           esp,ebp
0040B7C1     pop           ebp
0040B7C2     ret

归纳调用fun的过程为:

(1)参数入栈
(2)调用fun,保护断点,EIP入栈(内部完成,无汇编代码)
(3)保护寄存器ebp
(4)定位新的ebp,此后ebp一般不变
(5)保护ebx,esi,edi
(6)初始化40Bytes间隔空间和fun内部变量

此过程,数据空间变化如下:

(1)参数入栈
       |低地址|...|参数值|...|高地址| ...

                         ^esp指向此                     ^ebp指向某一位置

(2)调用fun,保护断点,EIP入栈(内部完成,无汇编代码)

       |低地址|...|fun返回函数地址|参数值|...|高地址| ...

                         ^esp指向此                                                  ^ebp指向某一位置

(3)保护寄存器ebp

       |低地址|...|ebp入栈值|fun返回函数地址|参数值|...|高地址| ...

                         ^esp指向此                                                       ^ebp指向某一位置

(4)定位新的ebp,此后ebp一般不变

       |低地址|...|ebp入栈值|fun返回函数地址|参数值|...|高地址| ...

                         ^esp和ebp指向此                                                

(5)保护ebx,esi,edi

       |低地址|...|edi入栈值|esi入栈值|ebx入栈值|40Bytes间隔空间|fun内部变量值|ebp入栈值|fun返回函数地址|参数值|...|高地址| ...

                         ^esp指向此                                   ^ebp指向(ebp入栈值)                                      

(6)初始化40Bytes间隔空间和fun内部变量

曾看到一程序:

#include "stdio.h"

int fun()
{
int a=0;
int* p=&a;
p=p+2;
*p=*p+3;

return 0;
}

int main(int argc, char* argv[])
{
int i=1;

fun();
i++;
printf("%d",i);

return 0;
}

下面是其中两段汇编代码:

.......
15:     int i=1;
0040B558     mov           dword ptr [ebp-4],1
16:
17:     fun();
0040B55F   call          @ILT+10(fun) (0040100f)
18:     i++;
0040B564     mov           eax,dword ptr [ebp-4]
0040B567     add           eax,1
0040B56A     mov           dword ptr [ebp-4],eax
...

5:      int a=0;
0040B508     mov           dword ptr [ebp-4],0
6:      int* p=&a;
0040B50F     lea           eax,[ebp-4]
0040B512     mov           dword ptr [ebp-8],eax
7:      p=p+2;
0040B515     mov           ecx,dword ptr [ebp-8]
0040B518     add           ecx,8
0040B51B     mov           dword ptr [ebp-8],ecx
8:      *p=*p+3;
0040B51E     mov           edx,dword ptr [ebp-8]
0040B521     mov           eax,dword ptr [edx]
0040B523     add           eax,3
0040B526     mov           ecx,dword ptr [ebp-8]
0040B529     mov           dword ptr [ecx],eax
9:
10:     return 0;
0040B52B     xor           eax,eax
11:     }
...

其数据空间为:

       |低地址|...|40Bytes间隔空间|p的值|a的值|ebp入栈值|fun返回函数地址|参数值|...|高地址| ...

                                                                               ^ebp指向|ebp入栈值|

由于p=&a,p指向|a的值|,则执行p=p+2后,p指向|fun返回函数地址|

跟踪程序|fun返回函数地址|=0040B564 ,执行的*p=*p+3,|fun返回函数地址|=0040B567   

即fun返回后程序从地址0040B567执行,跳过0040B564 处的代码mov           eax,dword ptr [ebp-4],使得结果i=1,而不是i=2。

阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 天津中医皮肤放心津门 网上哪里买药放心 强生泌尿医院好吗放心 网上哪个网站买药放心 放手 放手2012 放手图片 放手吧 放手去爱 就放手吧 放手爱 该放手 前夫请放手 放手句子 难以放手 放手by瑞者 我不该放手 别放手 不想放手 凄美的放手 不放手 该放手了 绝不放手 就放手吧别想他什么歌 总裁追妻别放手 就放手吧别想他 就放手吧别想她 有一种爱叫放手 放手吧别想他 放手吧别想她 放手也是一种幸福 放手也是一种爱 总裁追妻别放手云念 市长大人请放手 有一种爱叫做放手 情不由己总裁请放手 100种放倒人绝招 戏命师大招怎么放 婉儿大招怎么放 芈月放招顺序 放个大招给你看歌词