6
6
- 汇编
7
7
author : Lin
8
8
---
9
- ## 0x00 开宗明义
9
+ # 0x00 开宗明义
10
10
对OS的兴趣一直都有。最近比较强。因为5月份广东红帽杯被血虐,想补强下二进制方面。后来发现自己之前的相关知识深度还不够,继续深入时,好多东西和OS绕不开。所以,在原来的基础上补下OS。写个OS这种标题,有点标题党,只是给自己定的一个目标。最终完成的功能包含以下,不能对比现在的Linux这种大型成熟的OS。
11
11
* 启动
12
12
* 基本的内存管理
@@ -30,9 +30,11 @@ author: Lin
30
30
31
31
这里,会着重从加载开始。有必要学习下汇编。所以,加载器我会自己写,参考的两本书,关于加载器的有些细节,没有说明,我会尽可能把自己已理解的说出来。我还专门买了本 Professional Assembly Language的中译本,来作为At&t汇编的参考。
32
32
33
- ## 0x01 加载器
33
+ # 0x01 加载器
34
34
加载器是OS启动的第一步。在使用PC的日常中,会出现磁盘主引导坏掉的情况,电脑会提示,No boot loader found。
35
- ![ Alt text] ( /images/1530951823888.png )
35
+
36
+ ![ Alt text] ( /images/1530951823888.png )
37
+
36
38
这是在Virtualbox里,找不到引导时的提示。结果就是OS启动不了了。
37
39
加载器是什么:
38
40
加载器是位于磁盘第一个扇区的特殊程序,它由BIOS加载,它负责加载OS的代码到特定位置,然后把执行权交给OS的初始化代码。
@@ -65,8 +67,10 @@ BIOS是为加载器的执行提供了环境。没有这个环境的话,加载
65
67
定加载器之前,熟悉下执行环境。
66
68
我使用的工具是bochs,可以调试OS,很牛的一个模拟器。
67
69
我是自己编译的,安装在/opt目录下,不影响系统。
68
- ![ Alt text] ( /images/1530955947696.png )
69
- ![ Alt text] ( /images/1530955971227.png )
70
+
71
+ ![ Alt text] ( /images/1530955947696.png )
72
+ ![ Alt text] ( /images/1530955971227.png )
73
+
70
74
71
75
72
76
看到了吧。
@@ -94,8 +98,9 @@ BIOS是为加载器的执行提供了环境。没有这个环境的话,加载
94
98
times 510-($-$$) db 0
95
99
dw 0xaa55
96
100
```
97
- 参考书里第一个代码,去掉了开头的org 0x7c00,不引用字符串的地址和调用函数DispStr。修改后的代码,调用int 10h的中断在屏幕上显示一个a,对应的ASCII是97.运行后,屏幕上成功出现了一个字母a。说明理解是对的。
98
- ![ Alt text] ( /images/1530968051043.png )
101
+ 参考书里第一个代码,去掉了开头的org 0x7c00,不引用字符串的地址和调用函数DispStr。修改后的代码,调用int 10h的中断在屏幕上显示一个a,对应的ASCII是97.运行后,屏幕上成功出现了一个字母a。说明理解是对的。
102
+ ![ Alt text] ( /images/1530968051043.png )
103
+
99
104
100
105
如果想显示一个字符串呢。
101
106
先分析下这段代码,
@@ -136,8 +141,8 @@ ld -o hello.bin --oformat=binary hello.o
136
141
dd if=hello.bin of=hello.img bs=512 count=1
137
142
dd if=/dev/zero of=hello.img skip=1 seek=1 bs=512 count=2879
138
143
```
139
- 生成的hello.img就是一个虚拟的软盘。加载到bochs里,就能显示出字符串了
140
- ![ Alt text] ( /images/1531017963301.png )
144
+ 生成的hello.img就是一个虚拟的软盘。加载到bochs里,就能显示出字符串了
145
+ ![ Alt text] ( /images/1531017963301.png )
141
146
有兴趣的话,可以多显示一些。定字符串时的地址使用的是绝对,担心和代码段有冲突,将ds值置为1,使用的内存是
142
147
0x0001:0x0000 - 0x0001:0xffff
143
148
内存里的变量,严格来说都是数据,Intel实模式下,就是这样的规则。
@@ -148,4 +153,4 @@ dd if=/dev/zero of=hello.img skip=1 seek=1 bs=512 count=2879
148
153
cs,就是代码段的段地址。它配合ip寄存器,指示了下个指令的位置。跳转时,如果是远跳转的话,cs寄存器的值也是会变的,但其他情况下,我们不会修改这个寄存器。
149
154
ds,数据段。这个比较自由。想把数据存在什么位置,都可以直接操作它。极端来说,我们可以设置ds的值和cs同段,把当前的代码修改掉。有点像二进制里的控制流劫持一样。为什么能这样做呢?因为实模式里没有任何保护机制。这也是后面保护模式优势。在编写汇编代码时,程序员要对内存的布局非常清楚,哪段内存是什么样的用途,要不然,自己把自己玩死了。
150
155
ss, 栈段。这个段是用来设置栈的。设置了它之后,再设置下sp和bp,就手动建立起来了一个栈。当然程序里可以有多个栈。切换到不同栈时,正确设置ss,sp, bp的值就可以了。
151
- gs,fs,es,额外段。8086提供的备用的段。除了在个别命令中有特别用途,这个程序员可以随便用。
156
+ gs,fs,es,额外段。8086提供的备用的段。除了在个别命令中有特别用途,这个程序员可以随便用。
0 commit comments