create account

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

View this thread on: hive.blogpeakd.comecency.com
· @geyu · (edited)
$2.53
从头写一个操作系统 09 (create an OS from scratch 09)
[lesson 10](https://github.com/cfenollosa/os-tutorial/tree/master/10-32bit-enter)
---------------

这一课,就不简单的翻译课文,因为作者只写了一点点,不过一切都在代码里。
让我们把代码拆开,看看16位实模式是如何跳转到32位保护模式的。

分析代码前,先想想,为什么会有16位实模式呢?

很久以前,大概1985年左右,那时的intel的CPU只有16位,16位就是代表CPU有16根电线接收数据(其实是16根电线发送数据,另外还有32根电线分两组,每组16根各自接受一组数据),DOS就是那个时代的操作系统,很多年过去了,intel的cpu进化成为32位,但intel为了保证硬件的向前兼容,统一计算机启动的第一步是进入16位模式,然后由引导区决定下一步的动作,这样如果是必须16位模式的DOS系统,一样可以在32位机器上工作。如果你玩树莓派,就会发现完全没有16位实模式这个说法,不过树莓派的启动也是很奇怪的,它先启动GPU,让GPU先读两个配置文件,然后才让ARMcpu工作,这是后话,以后讲到树莓派的时候再说。

32位保护模式与16位实模式是有本质区别的,cpu一次可以寻址32位的地址,也就是最大能够寻址到4G,怎么算的?
```
2^16 = 65536       约等于65K
2^20 = 1048575     约等于1M
2^32 = 4294967295  约等于4G
```
现在咱们都用64位的操作系统,还记得当年换64位操作系统的原因吗?大概2010年后,电脑内存越来越大,很快超过了8G,可尴尬的是32位操作系统无法寻址超过4G的内存地址,因为就算给CPU的32根电线
都传递高电平,也只有0XFFFF FFFF 这么几个F,内存是有8G,多出4G的空间,CPU的指头都不够数。64位操作系统是可以调动CPU所有64根电线的,如果让64根电线都是高电平,那么可以寻址到160亿G的内存地址。

16位与32位的区别就在于寻址的方式,也就是CPU如何把自己要什么地址告诉内存,16位是用``` 段地址 X 16+偏移地址 ```的方式寻址,能够寻址20位。到了32位CPU,使用更加安全虚拟内存的技术,上一节课已经说过。同一个32位CPU在执行16位模式时,通过调整一个开关,就能进入32位寻址能力的模式,这个开关就是代码中的cr0,当cr0的最低位的bit被置为1时,CPU进入32位保护模式。
[原代码](https://github.com/cfenollosa/os-tutorial/blob/master/10-32bit-enter/32bit-main.asm)[^1]
```nasm
switch_to_pm:
    cli ;                       1. 关闭中断
    lgdt [gdt_descriptor] ;     2. 加载 GDT descriptor
    mov eax, cr0
    or eax, 0x1 ;               3. 将cr0设置为32位模式
    mov cr0, eax
    jmp CODE_SEG:init_pm ;      4. far jump 
```
`lgdt` 加载 `gdt_descriptor` 的作用就是把`GDT`载入到GDTR寄存器中,其实就是载入了一个地址。
16位时`CS`寄存器里存的的段地址,进入`32位保护模式`后,`CS`中存的是`GDT`这个结构中的偏移量,比如本例中的GDT[代码][^2]为:

```nasm
gdt_start: ; don't remove the labels, they're needed to compute sizes and jumps
    ; the GDT starts with a null 8-byte
    dd 0x0 ; 4 byte
    dd 0x0 ; 4 byte

; GDT for code segment. base = 0x00000000, length = 0xfffff
; for flags, refer to os-dev.pdf document, page 36
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:
    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
```

可以看到 `CODE_SEG` 的值是` 0x08  (gdt-code -gdt_start)`,所以此时的`CS`寄存器中就存着`0x08`,
在保护模式下,`CS:IP`取指令地址的流程就成为了, CPU计算GDTR+CS 得到code段的真实base地址,然后以`IP`作为offset,得到最终指令的地址。当然在载入指令前会判断`code`段的`limit`是否小于`IP`,如果小于,则报告`段错误`,写C语言的人谁没碰到过`段错误`?当然C语言中的段错误,应该都是超出了LDTR的limit,LDTR中的L是local,GDTR中的G是global。

一旦进入到32位保护模式,立马天高地阔,不过首先要初始化所有的寄存器,因为寄存器在实模式时,只用了16位,现在可以让寄存器所有32位的能力都能发挥出来。由far jump 到BEGIN_PM lable执行32位下初始化寄存器的指令。下面就该进入kernel了!






[THE ORIGIN ARTICALE IN GITHUB:](https://github.com/cfenollosa/os-tutorial/tree/master/10-32bit-enter)[^3]
-----------------------------

>Concepts you may want to Google beforehand: interrupts, pipelining
>
>Goal: Enter 32-bit protected mode and test our code from previous lessons
>
>To jump into 32-bit mode:
>
>Disable interrupts
>Load our GDT
>Set a bit on the CPU control register cr0
>Flush the CPU pipeline by issuing a carefully crafted far jump
>Update all the segment registers
>Update the stack
>Call to a well-known label which contains the first useful code in 32 bits
>We will encapsulate this process on the file 32bit-switch.asm. Open it and take a look at the code.
>
>After entering 32-bit mode, we will call BEGIN_PM which is the entry point for our actual useful code (e.g. >kernel code, etc). You can read the code at 32bit-main.asm. Compile and run this last file and you will see >the two messages on the screen.

>Congratulations! Our next step will be to write a simple kernel
[^1]:https://github.com/cfenollosa/os-tutorial/blob/master/10-32bit-enter/32bit-switch.asm
Copyright:[BSD 3-Clause License  Copyright (c) 2018, Carlos Fenollosa](https://github.com/cfenollosa/os-tutorial/blob/master/LICENSE)
[^2]:https://github.com/cfenollosa/os-tutorial/tree/master/09-32bit-gdt/32bit-gdt.asm
Copyright:[BSD 3-Clause License  Copyright (c) 2018, Carlos Fenollosa](https://github.com/cfenollosa/os-tutorial/blob/master/LICENSE)
[^3]:https://github.com/cfenollosa/os-tutorial/blob/master/10-32bit-enter
Copyright:[BSD 3-Clause License  Copyright (c) 2018, Carlos Fenollosa](https://github.com/cfenollosa/os-tutorial/blob/master/LICENSE)

版权注明:见备注
👍  , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , and 355 others
properties (23)
authorgeyu
permlink09-create-an-os-from-scratch-09
categoryesteem
json_metadata{"links":["https://github.com/cfenollosa/os-tutorial/tree/master/10-32bit-enter","https://github.com/cfenollosa/os-tutorial/blob/master/10-32bit-enter/32bit-main.asm","https://github.com/cfenollosa/os-tutorial/tree/master/10-32bit-enter","https://github.com/cfenollosa/os-tutorial/blob/master/10-32bit-enter/32bit-switch.asm","https://github.com/cfenollosa/os-tutorial/blob/master/LICENSE","https://github.com/cfenollosa/os-tutorial/tree/master/09-32bit-gdt/32bit-gdt.asm","https://github.com/cfenollosa/os-tutorial/blob/master/LICENSE","https://github.com/cfenollosa/os-tutorial/blob/master/10-32bit-enter","https://github.com/cfenollosa/os-tutorial/blob/master/LICENSE"],"tags":["esteem","esteem-cn","steemstem","cn-stem","cn"],"app":"esteem/2.0.7-surfer","format":"markdown+html","community":"esteem.app"}
created2019-04-14 08:33:45
last_update2019-04-15 02:11:15
depth0
children6
last_payout2019-04-21 08:33:45
cashout_time1969-12-31 23:59:59
total_payout_value1.874 HBD
curator_payout_value0.657 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length4,675
author_reputation1,811,446,112,774
root_title"从头写一个操作系统 09 (create an OS from scratch 09)"
beneficiaries
0.
accountesteemapp
weight1,000
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id83,066,536
net_rshares4,391,521,842,971
author_curate_reward""
vote details (419)
@cn-stem ·
谢谢分享!

本文存在如下问题:
1. 如前所述,对开源代码的引用,请注明“作者”、“开源协议”、“出处”等信息;
2. 引用2中的链接有误;


properties (22)
authorcn-stem
permlinkre-geyu-09-create-an-os-from-scratch-09-20190414t165853136z
categoryesteem
json_metadata{"tags":["esteem"],"app":"steempeak/1.9.6"}
created2019-04-14 16:58:54
last_update2019-04-14 16:58:54
depth1
children1
last_payout2019-04-21 16:58:54
cashout_time1969-12-31 23:59:59
total_payout_value0.000 HBD
curator_payout_value0.000 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length74
author_reputation2,817,035,839,243
root_title"从头写一个操作系统 09 (create an OS from scratch 09)"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id83,089,313
net_rshares0
@geyu ·
谢谢,已修改
properties (22)
authorgeyu
permlinkre-cn-stem-2019415t95843863z
categoryesteem
json_metadata{"tags":["esteem"],"app":"esteem/2.0.7-surfer","format":"markdown+html","community":"esteem.app"}
created2019-04-15 01:58:45
last_update2019-04-15 01:58:45
depth2
children0
last_payout2019-04-22 01:58:45
cashout_time1969-12-31 23:59:59
total_payout_value0.000 HBD
curator_payout_value0.000 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length6
author_reputation1,811,446,112,774
root_title"从头写一个操作系统 09 (create an OS from scratch 09)"
beneficiaries
0.
accountesteemapp
weight1,000
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id83,111,174
net_rshares0
@davidke20 ·
不错。腿开始粗了。加油😂

Posted using [Partiko Android](https://partiko.app/referral/davidke20)
👍  
properties (23)
authordavidke20
permlinkdavidke20-re-geyu-09-create-an-os-from-scratch-09-20190415t034233707z
categoryesteem
json_metadata{"app":"partiko","client":"android"}
created2019-04-15 03:42:33
last_update2019-04-15 03:42:33
depth1
children1
last_payout2019-04-22 03:42:33
cashout_time1969-12-31 23:59:59
total_payout_value0.000 HBD
curator_payout_value0.000 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length84
author_reputation952,373,523,681,662
root_title"从头写一个操作系统 09 (create an OS from scratch 09)"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id83,115,144
net_rshares1,114,687,031
author_curate_reward""
vote details (1)
@geyu ·
哇噻,我都没搞清楚什么情况,谢谢拉哥鼓励!
properties (22)
authorgeyu
permlinkre-davidke20-2019415t115314371z
categoryesteem
json_metadata{"tags":["esteem"],"app":"esteem/2.0.7-surfer","format":"markdown+html","community":"esteem.app"}
created2019-04-15 03:53:15
last_update2019-04-15 03:53:15
depth2
children0
last_payout2019-04-22 03:53:15
cashout_time1969-12-31 23:59:59
total_payout_value0.000 HBD
curator_payout_value0.000 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length21
author_reputation1,811,446,112,774
root_title"从头写一个操作系统 09 (create an OS from scratch 09)"
beneficiaries
0.
accountesteemapp
weight1,000
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id83,115,585
net_rshares0
@robertyan ·
欢迎联系@team-cn和@ericet加入新手村参与讨论哦~

推荐阅读[《Steem指南》](https://steem-guides.github.io/steemh),学习更多关于Steem的知识和经验。
properties (22)
authorrobertyan
permlinkre-geyu-09-create-an-os-from-scratch-09-20190414t152028790z
categoryesteem
json_metadata{"tags":["esteem"],"users":["team-cn","ericet"],"links":["https://steem-guides.github.io/steemh"],"app":"steemit/0.1"}
created2019-04-14 15:20:30
last_update2019-04-14 15:20:30
depth1
children0
last_payout2019-04-21 15:20:30
cashout_time1969-12-31 23:59:59
total_payout_value0.000 HBD
curator_payout_value0.000 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length106
author_reputation16,909,391,530,163
root_title"从头写一个操作系统 09 (create an OS from scratch 09)"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id83,085,348
net_rshares0
@steemstem ·
re-geyu-09-create-an-os-from-scratch-09-20190415t025930138z
<div class='text-justify'> <div class='pull-left'> <center> <br /> <img width='200' src='https://res.cloudinary.com/drrz8xekm/image/upload/v1553698283/weenlqbrqvvczjy6dayw.jpg'> </center>  <br/> </div> 

This post has been voted on by the **SteemSTEM** curation team and voting trail. It is elligible for support from <b><a href='https://www.steemstem.io/#!/@curie'>@curie</a></b>.<br /> 

If you appreciate the work we are doing, then consider supporting our witness [**stem.witness**](https://steemconnect.com/sign/account_witness_vote?approve=1&witness=stem.witness). Additional witness support to the [**curie witness**](https://steemconnect.com/sign/account_witness_vote?approve=1&witness=curie) would be appreciated as well.<br /> 

For additional information please join us on the [**SteemSTEM discord**]( https://discord.gg/BPARaqn) and to get to know the rest of the community!<br />

Please consider setting <b><a href='https://www.steemstem.io/#!/@steemstem'>@steemstem</a></b> as a beneficiary to your post to get a stronger support.<br />

Please consider using the <b><a href='https://www.steemstem.io'>steemstem.io</a></b> app to get a stronger support.</div>
properties (22)
authorsteemstem
permlinkre-geyu-09-create-an-os-from-scratch-09-20190415t025930138z
categoryesteem
json_metadata{"app":"bloguable-bot"}
created2019-04-15 02:59:33
last_update2019-04-15 02:59:33
depth1
children0
last_payout2019-04-22 02:59:33
cashout_time1969-12-31 23:59:59
total_payout_value0.000 HBD
curator_payout_value0.000 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length1,174
author_reputation262,017,435,115,313
root_title"从头写一个操作系统 09 (create an OS from scratch 09)"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id83,113,344
net_rshares0