从头写一个操作系统 07 (create an OS from scratch 07)

in #code6 years ago (edited)

lesson 9

你需要自己去查: GDT

本节目标: 编写 GDT

还记得lesson 6的segmentation吗?段地址左移一位,只有16位的寻址总线却达到了20位的寻址能力。

在32位模式下,段地址的使用方法有了变化。现在,偏移量是GDT中段描述符的索引。段描述符定义了基础地址(32位)、地址范围(20位)和其他一些标志位(只读,权限等)。更让人容易迷惑的是GDT的数据结构有点奇怪,打开os-dev.pdf看第34页,或者GDT的维基。

编写GDT最简单的方式是定义两个段,一个是代码段,另一是数据段。让它们重叠在一起放弃对内存的保护,今后我们会用c语言来修复这个缺陷。

第一个GDT入口必须是0x00,确保程序员管理内存是没有出错

然后,CPU不能直接加载GDT地址,它需要先取得一个GDT的大小(16bit)、地址(32bit)的数据结构(GDT descriptor)。用lgdt操作符加载GDT descriptor即可。

让我们直接跳转到GDT的汇编代码。这一节的理论比较复杂,最后仔细看看os-dev上的内容。

gdt_start: ; 不要更改这个标签,后面计算gdt大小会用到
    ; GDT以8个字节的空字节开始
    dd 0x0 ; 4 byte
    dd 0x0 ; 4 byte

; code段的GDT. base = 0x00000000, length = 0xfffff
;  os-dev.pdf 的36页有flags的详细介绍
gdt_code: 
    dw 0xffff    ; segment length, bits 0-15
    dw 0x0       ; segment base, bits 0-15
    db 0x0       ; segment base, bits 16-23
    db 10011010b ; flags (8 bits)
    db 11001111b ; flags (4 bits) + segment length, bits 16-19
    db 0x0       ; segment base, bits 24-31

; GDT for data segment. base and length identical to code segment 翻译同上
; some flags changed, again, refer to os-dev.pdf
gdt_data:
    dw 0xffff
    dw 0x0
    db 0x0
    db 10010010b
    db 11001111b
    db 0x0

gdt_end:

; GDT descriptor
gdt_descriptor:
    ;size的取值范围为165536,但内存地址0xFFFF == 65535 ,所以1-65536  ->   0 - 65535 这样作为对应,所以减去1。
    dw gdt_end - gdt_start - 1 ; size (16 bit), always one less of its true size
    
    dd gdt_start ; address (32 bit)

; define some constants for later use
CODE_SEG equ gdt_code - gdt_start
DATA_SEG equ gdt_data - gdt_start

下一节课,我们会完成32位保护模式的跳转,并且测试今天的代码。

THE ORIGIN ARTICALE IN GITHUB:

Concepts you may want to Google beforehand: GDT

Goal: program the GDT

Remember segmentation from lesson 6? The offset was left shifted
to address an extra level of indirection.

In 32-bit mode, segmentation works differently. Now, the offset becomes an
index to a segment descriptor (SD) in the GDT. This descriptor defines
the base address (32 bits), the size (20 bits) and some flags, like
readonly, permissions, etc. To add confusion, the data structures are split,
so open the os-dev.pdf file and check out the figure on page 34 or the
Wikipedia page for the GDT.

The easiest way to program the GDT is to define two segments, one for code
and another for data. These can overlap which means there is no memory protection,
but it's good enough to boot, we'll fix this later with a higher language.

As a curiosity, the first GDT entry must be 0x00 to make sure that the
programmer didn't make any mistakes managing addresses.

Furthermore, the CPU can't directly load the GDT address, but it requires
a meta structure called the "GDT descriptor" with the size (16b) and address
(32b) of our actual GDT. It is loaded with the lgdt operation.

Let's directly jump to the GDT code in assembly. Again, to understand
all the segment flags, refer to the os-dev.pdf document. The theory for
this lesson is quite complex.

In the next lesson we will make the switch to 32-bit protected mode
and test our code from these lessons.

Sort:  

今天忙些,出了乱子搞到现在才忙完。支持了。

Posted using Partiko Android

感谢感谢!能来看看就是我的荣幸,我现在心里全是感激!

拉哥,新人应该引导他。这么好的文章,埋没了

Posted using Partiko Android

这新人的注册日期比我早

Posted using Partiko Android

捂脸,这帖子拿来发esteem 好浪费,20几刀的帖子。变成0.5刀。真流汗

Posted using Partiko Android

你抱过,知道是啥样子的。“新人”没,说不定抱一下抱不到反而被冤枉抄袭,说不定以后就没了。有时,不适合操之过急🤓既然我看到你上面提议了,以后未来大腿就交给你照顾了哈😘

Posted using Partiko Android

哎玛,鸭力好大。我还是躲起来好了,

Posted using Partiko Android

拉哥。为什么不撸stem

Posted using Partiko Android

这个不是在跟我说的吧?

你不是拉仔吗?

Posted using Partiko Android

不是呀,我是拉哥的小弟,不是拉哥的小号😂

把标签改两个,换成steemstem 和cn-stem

Posted using Partiko Android

多谢多谢,我玩的少,还不太会玩,抱大腿了!

注意,记得你说过的别把点赞看得太重就行了。审查员的留言,看得顺眼就看,看不顺就飘过好了。

Posted using Partiko Android

嗯嗯,不会忘,精力肯定要在编程上,重头戏还没开始呢,可不能松懈😁

Thanks for using eSteem!
Your post has been voted as a part of eSteem encouragement program. Keep up the good work! Install Android, iOS Mobile app or Windows, Mac, Linux Surfer app, if you haven't already!
Learn more: https://esteem.app
Join our discord: https://discord.gg/8eHupPq