[04] operating system made from real mode to protected mode

Through the efforts of the first three chapters, we successfully transfers control to the loader.asm this program. Specifically by bios is loaded and jump to 0x7C00 (IMB uncle were given) transfers control to the first assembler mbr.asm our operating system, and then in mbr.asm do is by loading a program loader and jump to 0x900 (this is our own given) transfers control to the loader.asm program, this program is only the current output line of the string "loader" to the screen, and today we will extend it. And today we need to do, it is the first operating system in a wonderful place, is across from real mode to protected mode .

First, the real-mode and protected mode bird's-eye view

I like this man face the problem, in fact, this chapter simply wants to understand the three major issues on the line, what is real and protected mode, what is the difference between real mode and protected mode is how to enter the protected mode. I would like to briefly discusses the next three issues

What is real and protected mode

Intel 8086 is a 16-bit microprocessor chip Intel in 1978 by design, is the originator of the x86 architecture. Then Intel launched its first 32-bit cpu Intel 80286 (soon to be phased out, some of the more classic 80386), this due to the cpu and before there are many different "protection" feature, so called protected mode, and also the 8086 16-bit cpu only the real mode is called the meantime, before.

So what is real and protected mode, in fact, give a name Intel processor features its own life only, and that is what features have the specific details, but at least one thing has just been revealed that at least a protected mode are 32-bit, and 16-bit real mode (even if a 32-bit real mode also cpu)

What is the difference between real mode and protected mode is

  1. Real-mode 16-bit, 32-bit protected mode
  2. The address is real mode segment address offset register 4 + offset address to obtain the physical address. Protected mode segment register into a segment selector, looking in the segment base descriptor table, plus the offset address to obtain a physical address (logical address to open the next tab)
  3. I think this is a corollary 1, is the real-mode address space is 1M, protected mode is 4G
  4. I think this is Corollary 2, that is, the authority recorded segment descriptor table, changing the real mode can freely access all memory of hidden (this is also reflected in the protection of these two words)

How to enter protected mode

Enter protected mode there are three steps:

  1. Open A20
  2. Load gdt
  3. The cr0 position of pe 1

It can be seen entering the protected mode of operation is very simple, but to make preparations in advance, the most important thing is gdt (Global Descriptor Table Global Descriptor Table) preparation.

Second, the code bird's-eye view

loader.asm

section loader vstart=0x900

jmp protect_mode

gdt:
;0描述符
    dd  0x00000000
    dd  0x00000000
;1描述符(4GB代码段描述符)
    dd  0x0000ffff
    dd  0x00cf9800
;2描述符(4GB数据段描述符)
    dd  0x0000ffff
    dd  0x00cf9200
;3描述符(28Kb的视频段描述符)
    dd  0x80000007
    dd  0x00c0900b

lgdt_value:
    dw $-gdt-1  ;高16位表示表的最后一个字节的偏移(表的大小-1) 
    dd gdt      ;低32位表示起始位置(GDT的物理地址)

SELECTOR_CODE   equ 0x0001<<3
SELECTOR_DATA   equ 0x0002<<3
SELECTOR_VIDEO  equ 0x0003<<3

protect_mode:
;进入32位
    lgdt [lgdt_value]
    in al,0x92
    or al,0000_0010b
    out 0x92,al
    cli
    mov eax,cr0
    or eax,1
    mov cr0,eax
    
    jmp dword SELECTOR_CODE:main
    
[bits 32]
;正式进入32位
main:
mov ax,SELECTOR_DATA
mov ds,ax
mov es,ax
mov ss,ax
mov esp,LOADER_STACK_TOP
mov ax,SELECTOR_VIDEO
mov gs,ax

mov byte [gs:0xa0],'3'
mov byte [gs:0xa2],'2'
mov byte [gs:0xa4],'m'
mov byte [gs:0xa6],'o'
mov byte [gs:0xa8],'d'

jmp $

Here to talk about my feelings and experiences, and now look at the whole of each line of code though not let myself write can write, but now it seems very clear. I actually can not remember now why did understand a very long time is to understand not, debug ages also always have problems. But this is the code I removed some non-essential part of understanding the impact, leaving only the most essential part, I do not know whether such a code in place if I can understand the initial contact.

Aerial view of entire sections of code, probably divided into three.

  • The first piece written in binary mode network data (four segment descriptor) memory, and defines three constants
  • The second block is the fact, careful observation will find the step of entering protected mode (open A20, GDT loading, the position of the pe cr0 1)
  • A third block or output "32mod" string on the screen, which is different from the previous output in protected mode

Third, an interpretation of the code: the global descriptor table (GDT)

cpu with the operating system to play with the way

One thing to say now may not realize, wrote back you will find a lot of places, like load gdt this mode of operation are common to a lot of places, we not control what gdt is short, there will be a lot of cpu and operating systems with each other playing with the place, this is one of them. How to play with it, and that is a good cpu define a data structure, give you a register. Operating systems are generally responsible for doing three things

  1. A responsible position to write a bunch of data (such as this lecture descriptor table gdt, and say after page tables) in accordance with the data structure in memory
  2. Then put what you wrote in memory of this position information (starting address), there is a cpu to you reserved a register, which generally have a specific command, such as this lecture lgdt, I will not tell you to use mov operation
  3. The operating system of a register in a cpu positions 1

Then turn on this feature, so descriptor table, page table so, TSS is also true, talked about after this will be fully understood. I now have some experience, but have not sorted out where to play with all of this, and so I'll give you some sort of a depth.

Let us talk about what is the descriptor

Directly on the dry, still remember the first lesson of said content

In the moment you boot, CPU registers are forced to a PC initialized 0xFFFF0. Moreover, if more specific, the CPU will segment base register is initialized to 0xF000 cs, the offset is initialized to the address register IP 0xFFF0, calculation rules based on the final address in the real mode, the segment base 4 to the left, plus the offset address to obtain a final physical address that is abstracted from the PC register address 0xFFFF0.

This left four segment base, plus an offset address to obtain the physical address mode, address translation is in real mode.

However, protected mode is not the same

In protected mode, the segment base register is stored data, it is understood to segment selector , to our own written in the memory according to the value descriptor table in looking for, find the corresponding segment descriptor , removed from section base address . With this segment base address plus an offset, the final physical address (after page table address and the logical thing to say, not in conflict).

It's that point of difference

That naturally have two problems, one is the descriptor table look like it? Determine what we write to memory data structure Yes. Another is where to find the descriptor table pressure, this would need to tell us in advance to reserve a good cpu registers, which is lgdt instruction. Here we are looking at two issues

Descriptor table look like

First descriptor table is a table in memory is a array , a segment descriptor is one of two next results. So we have to understand descriptor look like just fine

Here I am the way the selectors and GDTR register structure also listed, and these are all need our own place to write data, and also cpu and operating system with all the things that need to convention

;0描述符
    dd  0x00000000
    dd  0x00000000
;1描述符(4GB代码段描述符)
    dd  0x0000ffff
    dd  0x00cf9800
;2描述符(4GB数据段描述符)
    dd  0x0000ffff
    dd  0x00cf9200
;3描述符(28Kb的视频段描述符)
    dd  0x80000007
    dd  0x00c0900b

We look at these write directly in memory died constant, according to the data structure descriptor is written

Is converted to the binary code segment 00000000_00000000_11111111_11111111_00000000_11001111_10011000_00000000
data segment descriptor into a binary 00000000_00000000_11111111_11111111_00000000_11001111_10010010_00000000
video descriptor is converted to binary 10000000_00000000_00000000_00000111_00000000_11000000_10010000_00000000

Here we take a video segment descriptor to analyze, extract (put together) a data segment base, 00000000_00000000_10000000_00000000, is converted to hexadecimal 0x80000. How about cooked not familiar with, which happens to be black and white graphics mode in memory starting address mapping. We can look at the contents of the first chapter, but I'm still here to map out stickers.

The next few constants defined, it is easy to understand what they mean

lgdt_value:
    dw $-gdt-1  ;高16位表示表的最后一个字节的偏移(表的大小-1) 
    dd gdt      ;低32位表示起始位置(GDT的物理地址)

SELECTOR_CODE   equ 0x0001<<3
SELECTOR_DATA   equ 0x0002<<3
SELECTOR_VIDEO  equ 0x0003<<3

lgdt_value 就是按照 lgdt 寄存器规定的数据结构拼凑出来的,下面的三个常量其实就是对应上面定义的三个段描述符的偏移量,由于每个描述符占 64 位,也就是占 8 个地址单元,所以索引下标的计算就是第几个描述符 * 8就好了,相信这个不难理解。

四、代码第二块解读:进入保护模式三步走

代码直接对应上面的三步

加载 gdt

lgdt [lgdt_value]

打开 A20

in al,0x92
or al,0000_0010b
out 0x92,al
cli    ;禁止中断,先不用管

将 cr0 的 pe 位置 1

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

此时已经进入保护模式了,段基址寄存器的意义已经变了,所以跳转指令变成了

jmp dword SELECTOR_CODE:main

五、代码第三块解读:保护模式下的简单代码

前面就是将数据段寄存器赋值给一些段基址寄存器用于访问数据段,然后将栈基址赋值位本次加载到的内存位置,重点是下面几句

mov ax,SELECTOR_VIDEO
mov gs,ax
mov byte [gs:0xa0],'3'
...

这段将我们刚刚写好的常量 SELECTOR_VIDEO 写入了段基址寄存器 gs,并在其后用了这个基址寄存器去进行 mov 操作。通过这个段选择子,在段描述符表里寻找出来的段基址是我们写好的显卡的内存映射的起始地址,所以同前几章在实模式下的输出就一样了。

六、运行代码

我们并没有增加新文件,所以Makefile和上一篇一样,不用变,直接运行看效果,make brun

可以看到,我们的段基址寄存器没有直接写显卡的起始地址,而是通过段选择子索引的,但依然正常输出了 "32mod" 字符串,说明成功了

写在最后:开源项目和课程规划

如果你对自制一个操作系统感兴趣,不妨跟随这个系列课程看下去,甚至加入我们,一起来开发。

参考书籍

《操作系统真相还原》这本书真的赞!强烈推荐

项目开源

项目开源地址:https://gitee.com/sunym1993/flashos

当你看到该文章时,代码可能已经比文章中的又多写了一些部分了。你可以通过提交记录历史来查看历史的代码,我会慢慢梳理提交历史以及项目说明文档,争取给每一课都准备一个可执行的代码。当然文章中的代码也是全的,采用复制粘贴的方式也是完全可以的。

如果你有兴趣加入这个自制操作系统的大军,也可以在留言区留下您的联系方式,或者在 gitee 私信我您的联系方式。

课程规划

本课程打算出系列课程,我写到哪觉得可以写成一篇文章了就写出来分享给大家,最终会完成一个功能全面的操作系统,我觉得这是最好的学习操作系统的方式了。所以中间遇到的各种坎也会写进去,如果你能持续跟进,跟着我一块写,必然会有很好的收货。即使没有,交个朋友也是好的哈哈。

目前的系列包括

Guess you like

Origin www.cnblogs.com/flashsun/p/12233407.html