C程序运行时内存结构分析

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

C程序运行时内存结构分析

时间:2015-11-24 22:25点击:37次

实验知识

∙静态变量存储在静态存储区,局部变量存储在动态存储区(栈),代码存放在代码区

∙寄存器,EBP指向栈底,ESP指向栈顶,EIP指向正在执行指令的下一条指令,三个寄存器中保存的都是地址,32位系统,地址为4个字节即dword

∙所有写在函数定义里面的语句都编译成指令(驱动CPU)

实验代码

#include

<stdio.h>

int fun(int a, int b);

int m

= 10;

int main()

{

int i

= 4;

int j

= 5;

m

=

fun(i,

j);

}

int fun(int a, int b)

{

int c

= 0;

c

= a +

b;

return c;

}

这段代码包含两个函数,因此可以测试函数调用,此外还包含了静态变量、局部变量、返回值等

实验测试

测试工具:VC6.0

源代码及对应的汇编如下

寄存器及内存状态如下

EBP 栈顶初始值为0018FF84h ,ESP 初始为0018FF48h

ESP 和EBP 在栈中的作用

在每个函数最开始的地方有两条语句 push ebp

mov ebp,esp

在函数返回前也有两条语句

mov

esp,ebp

pop

ebp

每运行一个函数就新开一段栈空间,所谓的开栈空间就是移动ebp栈底,在移动ebp之前,通过push ebp保存上一级函数的栈底,然后用ebp指向现在函数栈的栈顶,即为当前函数开辟了栈;接着给局部变量进行地址分配以及保存现场等,esp不断向低地址移动,当函数调用结束时,esp指回当前函数的栈顶(mov esp,ebp),然后上一级函数的栈顶地址出栈保存在ebp中(pop ebp)。因此,每一个函数的栈顶上面都保存着上一级函数的栈顶地址,用于当前函数结束时能够返回上一级函数的栈,通过ebp和esp以及压栈出栈操作对栈进行维护。

逐条分析

main函数对应的汇编代码如下

7: int main()

8:

{

00401020 push ebp /

/ ebp初始为0018FF84h压栈,压栈后esp = 0018FF48h - 4 =

0018FF44h

00401021 mov ebp,esp /

/ ebp保存栈顶0,ebp=esp=0018FF44h

00401023 sub esp,48h /

/ esp -= 48h开辟了一段栈空间,留待后面保存局部变量,此时

esp=0018FF44h-48h=0018FEFCh

00401026 push ebx

00401027 push es

i

00401028 push edi /

/ ebx、esi和edi压栈,esp = 0018FEFCh - 4*3 = 0018FEF0h

00401029 lea edi,[ebp-48h] /

/ lea指令将ebp-48h作为偏移地址保存在edi中,

edi=0018FEFCh,即栈中ebx的上面

0040102C mov ecx,12h

00401031 mov eax,0CCCCCCCC

h

00401036 rep

stos dword ptr

[edi] //

将eax重复保存在以

edi开始的栈空间里,重

复次数为ecx次,向高

地址方向,共覆盖

12h*4=48h个地址,即

栈中保存ebx的地址以

上到ebp指向的地址这

一段全部填充为cch

9: int i

= 4;

00401038 mov dwor

d ptr [ebp-4],4 // 保

存变量i

10: int j

= 5;

0040103F mov dwor

d ptr [ebp-8],5 // 保

存变量j

11:

m = fun(i,

j);

00401046 mov eax,dwor

d ptr [ebp-8] // 将j保存在

eax中

00401049 push eax / / eax压栈, esp=0018FEF0h-4=0018FEECh

0040104A mov ecx,dwor

d ptr [ebp-4] // 将i保存在

ecx中

0040104D push ecx / / ecx压栈,esp=0018FEECh-4=0018FEE8h

0040104E call @ILT+0(_fun

) (00401005) // 以上实际上是为形

参分配内存,顺序从右到左,此步进行函数

跳转

00401053 add esp,8 /

/ 形参的地址回收,esp=0018FEE8h+8=0018FEF0h

00401056 mov [_

m

(00424a30)],eax //

返回值存放在静态变量m中

12: return 0;

0040105B xor eax,eax / / 返回值置为0

13:

}

0040105D pop ed

i

0040105E pop es

i

0040105F pop eb

x

00401060 add esp,48

h

00401063 cmp ebp,es

p

00401065 call __chkes

p (004010d0)

0040106A mov esp,eb

p

0040106C pop eb

p

0040106D re

t

fun函数的汇编代码理解

15: int fun(int a, int b)

16:

{

00401090 push eb

p

00401091 mov ebp,es

p

00401093 sub esp,44

h

00401096 push eb

x

00401097 push es

i

00401098 push ed

相关文档
最新文档