- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
用VC写Assembly代码⑹附录2[windows进程中的内存结构]
2006-06-08 23:21 1096人阅读评论(0)收藏举报 在阅读木文Z前,如果你连堆栈是什么多不知道的话,请先阅读文章后面的基础知识。
接触过编程的人都知道,高级语言都能通过变量名來访问内存中的数据。那么这些变量在内存屮是如 何存放的呢?程序乂是如何使用这些变量的呢?下面就会对此进行深入的讨论。下文中的C语言代码 如没有特别声明,默认都使用VC编译的release版。
首先,来了解一下C语言的变量是如何在内存分部的。C语言有全局变量(Global).木地变量 (Local),静态变量(Static).寄存器变量(Regeister)o每种变量都有不同的分配方式。先来看下面 这段代码:
ttincludc stdio. h
int gl二0, g2=0, g3=0;
int mainO
I
static int sl=0, s2=0, s3=0;
int vl=0, v2=0, v3=0;
//打印出各个变量的内存地址
printf(,,0x%08x/n\vl); 〃打印各本地变量的内存地址
printf(0x%08x/n,v2);
printf (,,0x%08x/n/n,, v3);
printf(,,0x%08x/n\gl); //打印各全局变量的内存地址
printf(0x%08x/n, g2);
printf(0x%08x/n/n, g3);
printf (,,0x%08x/n,,)sl); //打印各静态变量的内存地址
printf (,,0x%08x/n,z, s2);
printf(0x%08x/n/n, s3);
return 0;
}
编译后的执行结果是:
0x0012ff78
0x0012ff7c
0x0012ff80
0x004068d0
0x004068d4
0x004068d8
0x004068dc
0x004068e0
0x004068e4
输出的结果就是变量的内存地址。其中vl,v2,v3是本地变量,gl,g2,g3是全局变量,sl,s2,s3是静 态变量。你可以看到这些变虽在内存是连续分布的,但是本地变量和全局变量分配的内存地址差了十 万八千里,而全局变暈和静态变暈分配的内存是连续的。这是因为木地变暈和全局/静态变量是分配 在不同类型的内存区域中的结果。对于一个进程的内存空间而言,可以在逻辑上分成3个部份:代码 区,静态数据区和动态数据区。动态数据区一?般就是“堆栈”。“栈(stack)”和“堆(heap)”是两 种不同的动态数据区,栈足--种线性结构,堆足一种链式结构。进程的每个线程都有私有的“栈”, 所以每个线程虽然代码一样,但木地变量的数据都是互不干扰。一个堆栈可以通过“基地址”和“栈 顶”地址來描述。全局变量和静态变量分配在静态数据区,本地变量分配在动态数据区,即堆栈屮。 程序通过堆栈的基地址和偏移暈來访问木地变量。
{低端内存区域
I动态数据区I
I代码区I
I静态数据区I
1高端内存区域
堆栈是一个先进后出的数据结构,栈顶地址总是小于等于栈的基地址。我们可以先了解一下函数调用 的过程,以便对堆栈在程序中的作用有更深入的了解。不同的语言有不同的函数调用规定,这些因索 有参数的压入规则和堆栈的平衡。windows APT的调用规则和A7ST C的函数调用规则是不-?样的, 前者山被调函数调整堆栈,后者由调用者调整堆栈。两者通过_stdcall”和―cdecl”前缀区分。 先看下面这段代码:
ttincludc stdio. h
void _stdcal 1 func(int paraml, int param2, int param3)
{
int varl=paraml;
int var2=param2;
int var3=param3;
printfC0x%08x/n,Uml); //打印出各个变量的内存地址
printf(0x%08x/n, Dm2);
printf (0x%08x/n/n,伽3);
printf (,,0x%08x/n,, Avarl);
printf(0x%08x/n,var2);
pr intf C/0x%08x/n/n,, var3);
return;
}
int main()
{
func (1, 2, 3);
return 0;
}
编译后的执行结果是:
0x0012ff78
0x0012ff7c
0x0012ff80
0x0012ff68
0x0012ff6c
0x0012ff70
-函数执行时的栈顶(ESP)、低端内存区域
var 1
var 2
var 3
| RET |
I 1 — “_cdecl”函数返回后的栈顶(ESP)
parameter 1
param
文档评论(0)