• Linux内存寻址


    我会尽力以最简洁清晰的思路来写这篇文章。

    所谓内存寻址也就是从写在指令里的地址,转化为实际物理地址的过程。因为操作系统要兼顾许多东西,所以也就变得复杂。

    逻辑地址 → 线性地址 → 物理地址

    逻辑地址 = 段 + 偏移量

    因为:最开始cpu中的alu宽度只有16位,但地址总线宽度有20位。所以设置四个段寄存器:cs(指令),ds(数据),ss(堆栈),es(其它)。

    每个段寄存器16位,对应地址总线高16位。每条指令中的16位内部地址与某个段寄存器中内容相加,得到20位的实际地址。

    上述的16位内部地址到20位实际地址的转换还是8086的时代。

    到了80386,32位cpu的时代,许多情况都发生改变。其中一点:要实施“保护模式”。还要兼容过去的段寄存器。

    于是,之前的公式从新写为:

                 逻辑地址 = 段选择符(16位) + 偏移量(32位)

    所以对80386cpu的寻址还是要基于从前8086寻址方式来理解,《linux内核源代码情景分析》中这样描述:

    可简单记为:段寄存器(段选择符) → 地址段描述结构(段描述符) → 基地址 → 指令中发出的地址 + 基地址 = 物理地址

    地址段描述结构(段描述符) 从何而来:在cpu中增设两个寄存器,一个是全局性的段描述表寄存器GDTR;一个是局部性的段描述表寄存器LDTR。

                          段描述符地址  =  段选择符index字段×8 + gdtr/ldtr寄存器中的值

    这张图可以表现,怎样由段寄存器(段选择符)得到段描述符 。

    段选择符得到“段”的过程,一种是访问段描述表得到段描述符。

    另外还可以通过非编程寄存器,不访问段描述表得到段描述符。

    总之,是段选择符(段寄存器) → ( 段描述符表 → )段描述符 → 基地址的过程。

    段描述符:

    继续推导之前的式子:

                段描述符的获得:段选择符index字段×8 + gdtr/ldtr寄存器中的值

                基址 = 段描述符Base字段

                逻辑地址 = 段选择符(16位) + 偏移量(32位) = 段描述符Base字段 + 偏移量

    参考资料:

       《汇编语言》王爽

       《linux内核源代码情景分析》毛德操

       《Understanding the Linux Kernel》Daniel P. Bovet / Marco Cesati 

  • 相关阅读:
    sklearn 数据预处理1: StandardScaler
    Gitlab利用Webhook实现Push代码后的Jenkins自动构建
    Shell脚本-自动化部署WEB
    Jenkins可用环境变量以及使用方法
    Docker常用命令
    nginx中root和alias的区别
    gitlab+jenkins=自动化构建
    Spring Boot2.0:使用Docker部署Spring Boot
    Maven内置属性、POM属性
    navicat连接mysql出现Client does not support authentication protocol requested by server解决方案
  • 原文地址:https://www.cnblogs.com/rixiang/p/5049312.html
Copyright © 2020-2023  润新知