geyu avatar

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

geyu

Published: 12 Apr 2019 › Updated: 12 Apr 2019从头写一个操作系统 07 (create an OS from scratch 07)

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

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
    ; GDT8
    dd 0x0 ; 4 byte
    dd 0x0 ; 4 byte

; codeGDT. base = 0x00000000, length = 0xfffff
;  os-dev.pdf 36flags
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:
    ;size1655360xFFFF == 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.

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

Written by

btc bts

Read more #code posts


Best Posts From geyu

We have not curated any of geyu's posts yet. But you can encourage our curation team to review posts by visiting them regularly and by referring other readers. Because we give priority to frequently read content.

More Posts From geyu