MacOS环境-手写操作系统-05-保护模式超强寻址

简介: MacOS环境-手写操作系统-05-保护模式超强寻址

本文详细介绍了X86架构下保护模式的寻址机制,通过对比实模式,阐述了保护模式如何实现对4GB以上内存的访问。作者通过编写内核代码,创建指向5MB内存的描述符,并演示了读写这段内存的过程,以此展示保护模式的强大寻址能力。

摘要由CSDN通过智能技术生成

保护模式超强寻址

文章写于两年前的 MacBookAir(2015)

目前笔者为 MacBookPro M1 (抽查了部分 都运行正常)

Github项目地址: https://github.com/wdkang123/MyOperatingSystem

MacOS X86架构(x新版的arm架构的我没有 所以大家自行测试)

VirtualBox

C/C++环境 (Xcode必装)


1.简介

X86架构下 CPU运行模式分两种:


(1)实模式 早期的DOS 可以说是实模式的最好表现


(2)保护模式 在保护模式下 CPU的功能进一步增强 进而支撑起 计算繁重的图形用户界面


2.物理地址的计算

2.1 实模式寻址

Intel 8086 cpu,使用16位寄存器,16位数据总线,20位的地址总线,它的寻址方式是由段和偏移两部分组成,具体物理地址是这么计算的:


物理地址 = 段值 * 16 + 偏移


段值和偏移都只能用16位来表示,段值16位,16是等于2^4,所以段值16也就相当于一个20位的数字,由此段值16的数值不会超过1M,而偏移16位,能表示的地址范围也就不超过4K,因此整个物理地址能抵达的范围也就是1M + 4k.


2.2 保护模式寻址

在保护模式下,寻址方式完全就不同了


我们上一节讲过的GDT,全局描述符表 该表的表项就叫描述符(descriptor),在描述符中 专门抽出4个字节 也就是32位数据来表示内存的基地址


这样 内存访问一下子就达到了4G 在原来的实模式下 cs, ds这些16位的寄存器往往用来存储段值


在保护模式下 这些寄存器用来存储指向GDT某个描述符的索引


在保护模式下 访问某处的内存时 仍然使用 [寄存器:偏移] 的方式,但是CPU的对地址的计算方法不再使用上面的公式,而是把寄存器中的值当做访问GDT的索引,在GDT中找到对应的描述符,从描述符中获得要访问内存的基地址,然后将基地址加上偏移,进而得到要访问的具体地址。


由此,就突破了上面寻址公式的1M范围限制。如果我们在GDT中设置一个描述符,这个描述符所描述的基地址设置为5M,那么当我们用寄存器指向这个描述符时,系统就能够读取5M以上的内存了


2.3 构建指向5M内存地址描述符

接上节的部分


我们可以构造一个指向5M内存地址的描述符:


LABEL_DESC_5M: Descriptor 0500000h, 0ffffh, DA_DRW


0500000h = 5 * (2^20), 2^20 相当于1M,


于是0500000h相当于5M.接下来我们做一个实验,先将一段数据写入到5M的内存地址,然后再读取写入的数据,将读到的数据显示到屏幕上。


下面就是我们要写的内核代码(boot_read5M.asm):

 %include "pm.inc"

org   0x7c00

jmp   LABEL_BEGIN

[SECTION .gdt]
 ;                                  段基址          段界限                属性
LABEL_GDT:          Descriptor        0,            0,                   0  
LABEL_DESC_CODE32:  Descriptor        0,      SegCode32Len - 1,       DA_C + DA_32
LABEL_DESC_VIDEO:   Descriptor     0B8000h,         0ffffh,           DA_DRW
LABEL_DESC_5M:      Descriptor     0500000h,        0ffffh,           DA_DRW

GdtLen     equ    $ - LABEL_GDT
GdtPtr     dw     GdtLen - 1
           dd     0

SelectorCode32    equ   LABEL_DESC_CODE32 -  LABEL_GDT
SelectorVideo     equ   LABEL_DESC_VIDEO  -  LABEL_GDT
Selector5M        equ   LABEL_DESC_5M - LABEL_GDT

[SECTION  .s16]
[BITS  16]
LABEL_BEGIN:
     mov   ax, cs
     mov   ds, ax
     mov   es, ax
     mov   ss, ax
     mov   sp, 0100h

     xor   eax, eax
     mov   ax,  cs
     shl   eax, 4
     add   eax, LABEL_SEG_CODE32
     mov   word [LABEL_DESC_CODE32 + 2], ax
     shr   eax, 16
     mov   byte [LABEL_DESC_CODE32 + 4], al
     mov   byte [LABEL_DESC_CODE32 + 7], ah

     xor   eax, eax
     mov   ax, ds
     shl   eax, 4
     add   eax,  LABEL_GDT
     mov   dword  [GdtPtr + 2], eax

     lgdt  [GdtPtr]

     cli   ;关中断

     in    al,  92h
     or    al,  00000010b
     out   92h, al

     mov   eax, cr0
     or    eax , 1
     mov   cr0, eax

     jmp   dword  SelectorCode32: 0

     [SECTION .s32]
     [BITS  32]
LABEL_SEG_CODE32:
    mov   ax, SelectorVideo
    mov   gs, ax

    mov   si, msg
    mov   ax, Selector5M    ;用 es 指向5M内存描述符
    mov   es, ax
    mov   edi, 0

write_msg_to_5M:  ;将si指向的字符一个个写到5M内存处
    cmp   byte [si], 0
    je    prepare_to_show_char
    mov   al, [si]
    mov   [es:edi], al
    add   edi, 1
    add   si, 1
    jmp   write_msg_to_5M


prepare_to_show_char:
    mov   ebx, 10
    mov   ecx, 2
    mov   si, 0

showChar:
    mov   edi, (80*11)
    add   edi, ebx
    mov   eax, edi
    mul   ecx
    mov   edi, eax
    mov   ah, 0ch
    mov   al, [es:si]  ;由于es指向描述符LABEL_DESC_5M, 所以es:si 表示的地址是从5M开始的内存,si表示从5M开始后的偏移
    cmp   al, 0
    je    end
    add   ebx,1
    add   si, 1
    mov   [gs:edi], ax
    jmp   showChar
end: 
    jmp   $
    msg:
    DB     "This string is writeen to 5M memory", 0

SegCode32Len   equ  $ - LABEL_SEG_CODE32

再上节的基础上 我们增加了一个描述符Selector5M 用来指向5M以外的内存地址 在 write_msg_to_5M 中


由于es存储的是描述符LABEL_DESC_5M在GDT中的偏移 同时edi 初始化为0


因此[es:edi]表示从5M开始 偏移为0处的地址 mov [es:edi] , al, 就是将al的内容写入到5M偏移为0处的内存


也就是0500000h处的内存 每次循环edi都加1 于是第二次循环便将al的内容写入到内存0500001h处 依次类推


在showChar中,语句al, [es:si] 就是将5M内存处的数据读入到al中,一开始si初始化为0,所以第一次运行showChar代码,这一句将0500000h内存处的1字节数据存入al, 然后si加1,那么第二次运行时,该语句将0500001h内存处的字节信息写入到al, 依次类推


3.编译

nasm -o boot.bat boot_read5M.asm


生成 system.img


载入运行:

目录
相关文章
|
29天前
|
监控 Linux 云计算
Linux操作系统在云计算环境中的实践与优化###
【10月更文挑战第16天】 本文探讨了Linux操作系统在云计算环境中的应用实践,重点分析了其在稳定性、安全性和高效性方面的优势。通过具体案例,阐述了Linux如何支持虚拟化技术、实现资源高效分配以及与其他开源技术的无缝集成。文章还提供了针对Linux系统在云计算中的优化建议,包括内核参数调整、文件系统选择和性能监控工具的应用,旨在帮助读者更好地理解和应用Linux于云计算场景。 ###
37 3
|
1月前
|
存储 C语言 iOS开发
MacOS环境-手写操作系统-48-让内核从错误中恢复
MacOS环境-手写操作系统-48-让内核从错误中恢复
35 0
|
1月前
|
存储 API C语言
MacOS环境-手写操作系统-46,47-C语言开发应用程序
MacOS环境-手写操作系统-46,47-C语言开发应用程序
35 0
|
1月前
|
编译器 API C语言
MacOS环境-手写操作系统-45-C语言开发应用程序
MacOS环境-手写操作系统-45-C语言开发应用程序
44 0
|
1月前
|
小程序 iOS开发 MacOS
MacOS环境-手写操作系统-44-运行简单的程序
MacOS环境-手写操作系统-44-运行简单的程序
22 0
|
3月前
|
关系型数据库 MySQL 数据库
【Mac os系统】安装MySQL数据库
本文详细介绍了在Mac OS系统上安装MySQL数据库的步骤,包括下载、安装、配置环境变量、启动服务、授权设置以及解决常见问题,并提供了一些常用的MySQL命令。
200 0
【Mac os系统】安装MySQL数据库
|
4月前
|
Linux 虚拟化 iOS开发
部署06--MacOS安装VMware Fusion安装
部署06--MacOS安装VMware Fusion安装
|
3月前
|
测试技术 Linux 虚拟化
iOS自动化测试方案(五):保姆级VMware虚拟机安装MacOS
详细的VMware虚拟机安装macOS Big Sur的保姆级教程,包括下载VMware和macOS镜像、图解安装步骤和遇到问题时的解决方案,旨在帮助读者顺利搭建macOS虚拟机环境。
142 3
iOS自动化测试方案(五):保姆级VMware虚拟机安装MacOS
|
3月前
|
虚拟化 数据安全/隐私保护 iOS开发
VMware——安装MacOS 系统教程(仅供学习交流)
VMware——安装MacOS 系统教程(仅供学习交流)
74 4
|
5月前
|
Java Shell 开发工具
03. 【Java教程】在 MacOS 上安装 Java
03. 【Java教程】在 MacOS 上安装 Java
58 1