程序的内存映像
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是段内偏移地址。而段式地址变换由段表来实现,段表如下所示:
段表
然后根据段表来实现段式地址变化:
1、取出程序地址(S,W)
2、用S检索段表
3、判断主存是否越界(请看存储保护)
4、b+w即为所需要的主存地址
总结:所以我们通过CPU中分段部件中的寄存器CS、DS、SS中的内容来检索段表,找到段表中的对应信息,得到C程序中的内存映射区域。然后根据E**寄存器中存放的偏移地址,来确定我们需要的C程序映射内存中的一个存储单元地址。并且可以根据段表得到内存区域的起始地址和终止地址。
![](http://static.blog.csdn.net/xheditor/xheditor_emot/default/smile.gif)
理解有不当之处,请指出。这里只是个人理解,仅供参考,但请不要被误导。
首先,一个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 | ||
... | ||
s | L | b |
1、取出程序地址(S,W)
2、用S检索段表
3、判断主存是否越界(请看存储保护)
4、b+w即为所需要的主存地址
总结:所以我们通过CPU中分段部件中的寄存器CS、DS、SS中的内容来检索段表,找到段表中的对应信息,得到C程序中的内存映射区域。然后根据E**寄存器中存放的偏移地址,来确定我们需要的C程序映射内存中的一个存储单元地址。并且可以根据段表得到内存区域的起始地址和终止地址。
![](http://static.blog.csdn.net/xheditor/xheditor_emot/default/smile.gif)
理解有不当之处,请指出。这里只是个人理解,仅供参考,但请不要被误导。
相关文章推荐
- 程序的内存映像
- [Linux] ls和size命令以及程序内存映像、磁盘映像的理解
- 堆栈的详解(一):程序的内存映像
- C程序内存映像 有例子,有测试 memory representation of a C program
- [Linux] ls和size命令以及程序内存映像、磁盘映像的理解
- Anatomy of a Program in Memory—剖析内存中的一个程序(进程的虚拟存储器映像布局详解)
- 操作系统--内存中的程序映像(printf函数的运算顺序)
- C程序映像中内存的空间分布
- ls和size命令以及程序内存映像、磁盘映像的理解
- 【翻译】Anatomy of a Program in Memory—剖析内存中的一个程序(进程的虚拟存储器映像布局详解)
- 对程序的磁盘映像、内存映像、地址空间的理解 ,和 ls、size 命令
- 计算机程序中数据类型的内存映像
- 程序的内存映像
- [Linux] ls和size命令以及程序内存映像、磁盘映像的理解
- size 查看程序内存映像大小
- cownew开源-java程序内存一省再省
- 使用内存映射文件来提高你程序的性能
- 利用内存映射文件扩充程序可用的内存
- 内存驻留程序
- 给Java程序增加内存