加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Linux > 正文

linux – 分段寄存器使用

发布时间:2020-12-14 01:03:53 所属栏目:Linux 来源:网络整理
导读:我试图了解内存管理如何进入低级别并且有几个问题. 1)由Kip R. Irvine撰写的关于汇编语言的书说,在实模式中,前三个段寄存器在程序启动时加载了代码,数据和堆栈段的基址.这对我来说有点不合时宜.是手动指定这些值还是汇编程序生成将值写入寄存器的指令?如果
我试图了解内存管理如何进入低级别并且有几个问题.

1)由Kip R. Irvine撰写的关于汇编语言的书说,在实模式中,前三个段寄存器在程序启动时加载了代码,数据和堆栈段的基址.这对我来说有点不合时宜.是手动指定这些值还是汇编程序生成将值写入寄存器的指令?如果它自动发生,它如何找出这些段的大小?

2)我知道Linux使用扁平线性模型,即以非常有限的方式使用分段.此外,根据Daniel P. Bovet和Marco Cesati的“理解Linux内核”,有四个主要部分:用户数据,用户代码,内核数据和GDT中的内核代码.所有四个段都具有相同的大小和基址.我不明白为什么四个中只有它们的类型和访问权限不同(它们都产生相同的线性地址,对吧?).为什么不只使用其中一个并将其描述符写入所有段寄存器?

3)不使用分段的操作系统如何将程序划分为逻辑段?例如,他们如何在没有段描述符的情况下将堆栈与代码区分开来.我读过分页可以用来处理这些事情,但是不明白怎么做.

解决方法

扩展到 Benoit’s answer to question 3 ……

程序划分为逻辑部分,如代码,常量数据,可修改数据和堆栈,由不同的代理在不同的时间点完成.

首先,您的编译器(和链接器)创建指定此除法的可执行文件.如果你看一些可执行文件格式(PE,ELF等),你会发现它们支持某种类型的段或段或任何你想要它的名称.除了文件中的地址,大小和位置之外,这些部分还具有告诉操作系统这些部分的目的的属性,例如,这部分包含代码(这里是入口点),这是初始化的常量数据,即 – 未初始化的数据(通常不占用文件中的空间),这里是关于堆栈的东西,在那里有依赖项列表(例如DLL),等等

接下来,当操作系统开始执行程序时,它会解析文件,以查看程序需要多少内存,每个部分需要的内存和保护内容.后者通常通过页表完成.代码页被标记为可执行和只读,常量数据页被标记为不可执行和只读,其他数据页(包括堆栈的数据页)被标记为不可执行和读写.这应该是正常的.

通常,程序需要读写,同时需要动态生成代码的可执行区域,或者只能修改现有代码.组合的RWX访问可以在可执行文件中指定,也可以在运行时请求.

可以有其他特殊页面,例如用于动态堆栈扩展的保护页面,它们被放置在堆栈页面旁边.例如,您的程序以为64KB堆栈分配的足够页面开始,然后当程序试图访问超过该点时,操作系统拦截对这些防护页面的访问,为堆栈分配更多页面(最大支持的最大大小)和进一步移动防护页面.这些页面不需要在可执行文件中指定,操作系统可以自己处理它们.该文件应仅指定堆栈大小和可能的位置.

如果操作系统中没有硬件或代码来区分代码存储器和数据存储器或强制执行存储器访问权限,则该分区非常正式. 16位实模式DOS程序(COM和EXE)没有以某种特殊方式标记的代码,数据和堆栈段. COM程序在一个共同的64KB段中具有所有内容,它们以IP = 0x100和SP = 0xFFxx开始,并且代码和数据的顺序可以在内部任意,它们可以实际上自由地交织. DOS EXE文件仅指定了起始CS:IP和SS:SP位置以及代码,数据和堆栈段与DOS无法区分.它需要做的只是加载文件,执行重定位(仅限EXE),设置PSP(程序段前缀,包含命令行参数和一些其他控制信息),加载SS:SP和CS:IP.它无法保护内存,因为实际地址模式下没有内存保护,因此16位DOS可执行格式非常简单.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读