您的位置:首页 > 编程语言 > C语言/C++

程序的内存映像

2014-10-07 10:37 253 查看
这几天在看C语言的书籍,对C的内存映像有点疑惑,于是,查找资料,查阅了庞丽萍编著的《操作系统原理》第四版中的第七章主存管理中的段式系统,此外还看了王元珍、曹忠生、韩忠芬编著的《80X86汇编语言程序设计》得到了一个自己对在80X86结构下的内存映射的理解。不过也许自己的理解是错的或者有不到之处,希望大神能够指出理解的不足之处。

首先,一个C程序,在内存中的映射(当然这里指的是80X86系统)包括四个区域(这里是在看C语言大全的时候介绍的):

第一个区域是程序代码区域:存放的是程序代码。

第二个区域是全局变量区域:存放的是全局变量和静态变量等伴随着整个程序生存过程的数据。

第三个区域是栈(stack):用来保存函数调用时返回地址、函数变元、局部变量、CPU当前状态等临时的数据。

第四个区域是堆(heap):用来提供给程序员动态分配和释放的区域,比如使用malloc申请一段内存,就是在这个区域中申请的。

然后联系《80x86汇编语言程序设计》中介绍的Intel80X86微处理器结构中寄存器的知识,知道在处理器中的六大部件中,寄存器分为以下几个:

执行部件中的寄存器:

EAX:累加寄存器

EBX:基址寄存器

ECX:计数寄存器

EDX:数据寄存器

ESI:源变址寄存器

EDI:目的变址寄存器

ESP:堆栈指示寄存器,存放的是当前堆栈段中的栈顶的偏移地址

EBP:堆栈基址寄存器,存放的是该堆栈段中某一个存储单元的偏移地址

指令预取部件中的寄存器:

EIP:指令指示寄存器,存放的是下一条将要被CPU执行的指令的偏移地址(EA),它的值为该指令到所在段首地址的字节距离。

分段部件中的寄存器:

CS:代码段寄存器

SS:堆栈段寄存器

DS:数据段寄存器

联系两者的关系,我们可以这样认为:

C程序内存映射中的程序代码区域对应的是CS(代码段寄存器)中描述的虚拟内存区域;

C程序内存映射中的全局变量区域对应的是DS(数据段寄存器)中描述的虚拟内存区域;

C程序内存映射中的堆(heap)和栈(stack)对应的是SS(堆栈段寄存器)中描述的虚拟内存区域,其中堆(heap)从该段中的高低址向低地址分配,栈(stack)从该段中的低地址向高低址分配,两者公用一个段。

那么,我们如何通过分段部件中的寄存器CS、SS、DS来得到我们的内存地址呢。如何确定SS堆栈段中的起始地址和终止地址呢。这就要查阅《操作系统原理》中关于主存管理中的段式系统了。

在段式系统中,将主存分为很多个分区,每一个段占一个分区,对于一个段来说,它有自己的名字,是一个连续的地址区。在段式系统中,逻辑分段由代码分段、数据分段、栈段组成。刚好对应着上面代码段寄存器、堆栈段寄存器、数据段寄存器。用户通过给出段名(CS、SS、DS中的内容)和段内偏移地址(E**寄存器中的内容)来访问这些段(实际上,操作系统会用唯一的段号来替代该段的段名)。所以,一般的程序地址形式由(s,w)组成,S是段号,W是段内偏移地址。而段式地址变换由段表来实现,段表如下所示:

段表
段号长度基址
0  
...  
sLb
然后根据段表来实现段式地址变化:
1、取出程序地址(S,W)

2、用S检索段表

3、判断主存是否越界(请看存储保护)

4、b+w即为所需要的主存地址

总结:所以我们通过CPU中分段部件中的寄存器CS、DS、SS中的内容来检索段表,找到段表中的对应信息,得到C程序中的内存映射区域。然后根据E**寄存器中存放的偏移地址,来确定我们需要的C程序映射内存中的一个存储单元地址。并且可以根据段表得到内存区域的起始地址和终止地址。


理解有不当之处,请指出。这里只是个人理解,仅供参考,但请不要被误导。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息