MacOS环境-手写操作系统-04-实模式进入保护模式

简介: MacOS环境-手写操作系统-04-实模式进入保护模式

本文详述了在MacBook上从实模式切换到保护模式的过程,涉及汇编语言编程,包括GDT、段选择子和CR0寄存器的设置。代码示例展示了如何在保护模式下显示字符,并解释了保护模式的显著特点,如寻址空间的扩大和权限管理。文章还提到了代码的编译和运行步骤。

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

实模式进入保护模式

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

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

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

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

VirtualBox

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


1.简介

从实模式到保护模式


保护模式 最重要的就是“保护”两字


有了“保护”功能后 CPU为软件提供了很多的功能 当然也有了很多的限制


但是“保护”并不是几行字能描述清楚的 所以先把代码跑起来


2.汇编

%include "pm.inc"

org   0x9000

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

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

SelectorCode32    equ   LABEL_DESC_CODE32 -  LABEL_GDT
SelectorVideo     equ   LABEL_DESC_VIDEO  -  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   ebx, 10
    mov   ecx, 2
showChar:
    mov   edi, (80*11)
    add   edi, ebx
    mov   eax, edi
    mul   ecx
    mov   edi, eax
    mov   ah, 0ch
    mov   al, [si]
    cmp   al, 0
    je    end
    add   ebx,1
    add   si, 1
    mov   [gs:edi], ax
    jmp    showChar
end: 
    jmp   $
    msg:
    DB     "Protect Mode", 0

SegCode32Len   equ  $ - LABEL_SEG_CODE32

再看看 pm.inc 的内容

%macro Descriptor 3
    dw    %2  &  0FFFFh
    dw    %1  &  0FFFFh
    db   (%1>>16) & 0FFh
    dw   ((%2 >> 8) & 0F00h) | (%3 & 0F0FFh)
    db   (%1 >> 24) & 0FFh
%endmacro


DA_32       EQU 4000h   ; 32 位段
DA_C        EQU 98h ; 存在的只执行代码段属性值
DA_DRW      EQU 92h ; 存在的可读写数据段属性值

对上面的代码进行编译

nasm -o kernel.bat kernel.asm

从LABEL_SEG_CODE32: 这一部分开始 代码就执行在保护模式下 这段代码的作用就是显示一串字符 gs是计算机的一个寄存器 它跟eax,ebx这些寄存器差不多 但作用更为单一 主要用来指向显存 当我们将信息写入gs指向的内存后 信息会显示到屏幕上


用于显示字符的显存,内存地址从0XB800h开始,从该地址开始,每两个字节用来在屏幕上显示一个字符 这两个字节中 第一个字节的信息用来表示字符的颜色 第二个字节用来存储要显示的字符的ASCII值 屏幕一行能显示80个字符 大家看到代码中有语句


mov edi, (80*11)


这表明我们要从第11行开始显示字符,接下来又有语句:

add edi, ebx


其中,ebx的值是11,这表明我们要从第11行的第10列开始显示字符串,接下来的语句是:

mov eax, edi

mul ecx


ecx的值是2 这个2就是我们前面说过的显示一个字符需要两个字节


上面几句汇编语句的作用是:

eax = ((80*11) + 10) * 2

这样eax就指向了第11行第11列所在的显存位置


接下来语句:

mov ah, 0ch

它的作用是在用来显示字符的两字节中,对第一个字节放入数值0ch,也就是设置字符的颜色,接下来的语句:


mov al, [si]

将寄存器si指向的字符的ascii值写入到第二个字节,这样,字符就显示到屏幕上了。


大家注意寄存器si的用法:[si]. si相当于C语言中的一个指针,指向内存某个地址,[si]就是读取si指向的内存地址的信息,等同于 c语言中的*(si)


3.保护模式显著特点

1.寻址空间从时模式的1M增强到4G

2.不同的代码拥有不同的优先级,优先级高的能够执行特殊指令,优先级低的,某些重要指令就无法执行。


要想进入保护模式 我们需要解决两个问题:


(1)如何获取超过1M以上的内存地址


(2)如何设置不同代码所具有的优先级


我们先看看寻找能力的变化,在实模式下,cpu是16位的,寄存器16位,数据总线16位,地址总线20位


于是寻找的范围必然受限于20位的地址总线,所以寻找范围无法超过1M(2^20).


要想实现4GB的寻址 我们必须使用32位来表示地址 intel是这么解决这个问题的,他们用连续的8个字节组成的结构体来解决一系列问题:

byte0

byte1

……

byte7


其中,字节2,3,4以及字节7,这四个字节合在一起总共有32位,这就形成了一个32位的地址。


同时把字节0,字节1,以及将字节6的拆成两部分,各4个bits,前4个bits跟字节0,字节1合在一起,形成一个20个bit的数据,用来表示要访问的内存长度


这样,我们就解决了内存寻址的问题


4.pm.inc

pm.inc里面的宏定义就是我们说的7字节数据结构


%macro Descriptor 3

表示要初始化该数据结构 需要传入3个参数 :


(1) %1表示引用第一个参数


(2) %2表示引用第二个参数


初始化该结构时,输入的一个参数是内存的地址,大家看语句:

dw %1 & 0FFFFh

db (%1>>16) & 0FFh

这两句就是把内存地址的头三个字节放入到byte2,byte3,byte4,最后一句:


db (%1 >> 24) & 0FFh

就是讲地址的第4个字节放入到byte7. 初始化数据结构的第二个参数表示的是要访问的内存的长度,大家看语句:


dw %2 & 0FFFFh

就是把内存长度的头两个字节写入byte0,byte1,语句:


dw ((%2 >> 8) & 0F00h) | (%3 & 0F0FFh)

中的((%2 >> 8) & 0F00h)就是把内存长度的第16-19bit写入到byte6的前4个bit


由此要访问的内存和内存的长度就都设置好了


5.编译运行

将第2.汇编的代码进行编译


nasm boot.asm -o boot.bat


nasm kernel.asm -o kernel.bat


打开 java 工程 生成 system.img


最后 装载运行

目录
相关文章
|
30天前
|
监控 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
|
15天前
|
安全 Linux 数据安全/隐私保护
Vanilla OS:下一代安全 Linux 发行版
【10月更文挑战第30天】
37 0
Vanilla OS:下一代安全 Linux 发行版
|
18天前
|
人工智能 安全 Linux
|
4月前
|
安全 Linux 网络安全
部署07--远程连接Linux系统,利用FinalShell可以远程连接到我们的操作系统上
部署07--远程连接Linux系统,利用FinalShell可以远程连接到我们的操作系统上
|
1月前
|
Unix 物联网 大数据
操作系统的演化与比较:从Unix到Linux
本文将探讨操作系统的历史发展,重点关注Unix和Linux两个主要的操作系统分支。通过分析它们的起源、设计哲学、技术特点以及在现代计算中的影响,我们可以更好地理解操作系统在计算机科学中的核心地位及其未来发展趋势。
|
3月前
|
编解码 安全 Linux
基于arm64架构国产操作系统|Linux下的RTMP|RTSP低延时直播播放器开发探究
这段内容讲述了国产操作系统背景下,大牛直播SDK针对国产操作系统与Linux平台发布的RTMP/RTSP直播播放SDK。此SDK支持arm64架构,基于X协议输出视频,采用PulseAudio和Alsa Lib处理音频,具备实时静音、快照、缓冲时间设定等功能,并支持H.265编码格式。此外,提供了示例代码展示如何实现多实例播放器的创建与管理,包括窗口布局调整、事件监听、视频分辨率变化和实时快照回调等关键功能。这一技术实现有助于提高直播服务的稳定性和响应速度,适应国产操作系统在各行业中的应用需求。
109 3