发新话题
打印

操作系统学习笔记——引导

操作系统学习笔记——引导


由于没有买到《linux设备驱动程序》,但是老天对我还好,买到了本《自己动手写操作系统》,我跟着于渊前辈写的那些内容进行操作,中间有段没有弄明白,所以研究了一阵子,但是后来没有成功,结果就来这里问大家了,现在清楚了,也明白了。(在flw前辈的帮助下)
同时也感谢回答过我的问题的各位牛银!~~
把引导代码帖出来(代码非本人写的,是从书上抄的,把信息改了改)。
[code:1:945bfd6073] org 07c00h ; 告诉编译器程序加载到7c00处
mov ax, cs
mov ds, ax
mov es, ax
call DispStr ; 调用显示字符串例程
jmp $ ; 无限循环
DispStr:
mov ax, BootMessage
mov bp, ax ; ES:BP = 串地址
mov cx, 16 ; CX = 串长度
mov ax, 01301h ; AH = 13,  AL = 01h
mov bx, 000ch ; 页号为0(BH = 0) 黑底红字(BL = 0Ch,高亮)
mov dl, 0
int 10h ; 10h 号中断
ret
BootMessage: db "QQ:314064349"
times  510-($-$$) db 0 ; 填充剩下的空间,使生成的二进制代码恰好为512字节
dw  0xaa55 ; 结束标志[/code:1:945bfd6073]


用nasm编译成bin,命令
[code:1:945bfd6073]c:\>cd nasm\bin
c:\>nasm boot.asm -o boot.bin[/code:1:945bfd6073]

下面说明一下上面的命令

nasm是一种汇编语言的编译器(可以在win下用,linux下用等很多环境下使用,在baidu中,或者找我要,可以得到)

-o  是nasm里的一个命令参数
用过gcc的朋友会知道,gcc下的命令也如此:
[code:1:945bfd6073][1jjk@linux.com]$gcc 1jjk.c -o 1jjk[/code:1:945bfd6073]
这个  -o  和gcc里的 -o意思是一样的,最后的那个boot.bin是生成的目标文件,是二进制文件。

下面说说其他的一些命令:

-o参数:指定输出文件名
-f参数:指定输出文件格式
-l参数:输出列表文件
-E参数:输出错误信息到文件中
-s参数:输出错误信息到屏幕
-i参数:指定头文件路径
-p参数:预编译头文件
-d参数:预编译宏
-u参数:取消宏定义
-e参数:只预处理
-a参数:根本不预处理
-w参数:允许或禁止汇编警告信息

nasm更详细的说明书可以在我的主页里面找到:http://www.zggo.com/xoops
boot.asm是上面的那些汇编语言的源代码文件(在linux源代码会看到),
然后用打开vmware,将“软驱”选项设置为“选用软驱磁盘映像”就可以了,然后把生成的bin放进去就可以了

下面给大家放几张图片看一看!



参考书籍《自己动手写操作系统》作者:于渊

接受建议,改了一下!有笔误,请大家多多指点,多多批评!












 flw 回复于:2005-09-13 14:31:28
>>用nasm编译成bin
怎么编译?开关选项用什么?每个选项分别是什么意思?

>>然后用打开vmware,将“光驱”选项设置为“选用软驱磁盘映像”就可以了,
>>然后把生成的bin放进去就可以了
应该是软驱才对。

还有啊,你碰到的问题都有哪些?尽量也写一写。
如果别的新手(当然是有相关知识基础的)能够按照你的这篇文章来做出自己的东西,那么这篇文章才算是成功的。

临了,建议附上贴图一副,以说明你的程序能够达到什么样的效果。


 bleem1998 回复于:2005-09-13 14:46:52
那本书在下见过
感觉就是汇编堆出来的
不懂汇编的我买了==浪费钱


 1jjk 回复于:2005-09-13 14:57:12
[quote:4361cfde63="bleem1998"]那本书在下见过
感觉就是汇编堆出来的
不懂汇编的我买了==浪费钱[/quote:4361cfde63]

不仅仅是汇编!感觉那本书写的很好,因为我这么菜的菜鸟都能看懂!那其他有点功底的前辈就更不用说了,是吧?


 4℃華客 回复于:2005-09-13 15:43:32
菜鸟是说我吧,我知道那本书,等我看了再说说意见吧!


 solomoon 回复于:2005-09-13 15:43:40
我来跟图







 4℃華客 回复于:2005-09-13 15:55:35
哦 ,不错呀,我还以为写操作系统的没有几个,现在发现了,有个和1jjk  有相同的爱好了,^_^,明天借我看看你那本书,说什么也要跟的上社会呀!!


 zxh5187406 回复于:2005-09-13 15:57:44
这本书怎么样?


 1jjk 回复于:2005-09-13 16:14:16
像我这样的菜菜都看懂了,你说是不是好书呢?


 lovett 回复于:2005-09-13 16:49:25
那本书看了样章,感觉没意思,没什么新东西。


 mq110 回复于:2005-09-13 17:41:32
支持.呵呵~
还不懂汇编.


 renstone921 回复于:2005-09-13 18:26:04
times    510-($-$$)

兄弟,实在想不起来了.
$代表当前地址
$$代表什么?

太久不操汇编这把刀了.


 1jjk 回复于:2005-09-13 18:38:47
一个section的开始处被汇编后的地址


 1jjk 回复于:2005-09-13 18:39:29
在我的主页里应该有说明的
我转过去了详细的说明书


 renstone921 回复于:2005-09-13 18:42:55
好的,谢谢!


 zxh5187406 回复于:2005-09-14 12:12:54
- -有看到...看到名字有点扯就没买了...


 zhyesno 回复于:2005-09-16 11:03:48
不错,学习一下,有空动手看看。。。


 bleem1998 回复于:2005-09-21 12:07:08
[code:1:078c399efc]
   org   07c00h         ; 告诉编译器程序加载到7c00处
   mov   ax, cs
   mov   ds, ax
   mov   es, ax
   call   DispStr         ; 调用显示字符串例程
--truncated--
[/code:1:078c399efc]
请问第一句是什么意思呢
是说程序从07c00h开始运行?
还是别的意思?


 renstone921 回复于:2005-09-21 12:22:01
程序被加载到实地址07c00h处。


 bleem1998 回复于:2005-09-21 12:47:33
谁把程序加载到07c00h处呢?
自己把自己搬过去?


 flw 回复于:2005-09-21 12:49:09
[quote:35523abd3e="bleem1998"]谁把程序加载到07c00h处呢?[/quote:35523abd3e]
BIOS


 bleem1998 回复于:2005-09-21 12:59:50
是不是说BIOS一定会把程序搬到07c00h
而刚才那个程序只不过是告诉编译器一下而已
就算不告诉编译器BIOS依然会把程序搬到07c00h
right?


 renstone921 回复于:2005-09-21 13:01:48
wrong!


 _z_ 回复于:2005-09-21 13:05:21
[quote:5eefa38ce1="bleem1998"]是不是说BIOS一定会把程序搬到07c00h
而刚才那个程序只不过是告诉编译器一下而已
就算不告诉编译器BIOS依然会把程序搬到07c00h
right?[/quote:5eefa38ce1]

yes.
BIOS把启动扇区的代码加载到0x7c00,然后跳转到0x7c00开始执行。
可以看看bootsect.S


 bleem1998 回复于:2005-09-21 13:06:20
那是怎样的呢
讲讲阿老大


 bleem1998 回复于:2005-09-21 13:27:10
原来是这样
还有两个问题想请教

1,
在程序里告诉编译器07c00h这个地址的目的是什么呢?
是不是因为编译器要在程序里设置一些“绝对地址”的跳跃?

2,
我们平时用C写程序
这些程序的启动地址又是多少呢?
这个地址是由谁、在哪里设置的呢?


 1jjk 回复于:2005-09-21 13:45:19
这个啊?
买本书看看就知道了
说了那么多,不知道你有没有看!
也不知道你对引导有什么概念!
也不知道你有没有去认真思考问题


 _z_ 回复于:2005-09-21 14:36:42
[quote:78149f9444="bleem1998"]
1,
在程序里告诉编译器07c00h这个地址的目的是什么呢?
是不是因为编译器要在程序里设置一些“绝对地址”的跳跃?
[/quote:78149f9444]
看不出。。。:em19: 

[quote:78149f9444="bleem1998"]
2,
我们平时用C写程序
这些程序的启动地址又是多少呢?
这个地址是由谁、在哪里设置的呢?
[/quote:78149f9444]
一般是由连接器作的
比如ld --verbose看一下它的默认连接脚本,有__executable_start这样的东东。。。:em17:


 bleem1998 回复于:2005-09-21 14:54:03
这个对我来说难了点
3Q very much.


 renstone921 回复于:2005-09-21 15:07:09
在程序里告诉编译器07c00h这个地址的目的是什么呢? 

大致过程如下。
开机或热启动-->cpu的寄存器复位,其中指令指针寄存器的值被设置为0xfff0-->跳转到0xfff0--->系统进行post-->如果自捡成功--->把的中断向量复制到内存的低1kb存储单元内---所以系统最多有256个中断向量--->
然后根据bios的信息,找到引导扇区--->执行bios磁盘中断,从引导扇区读入引导纪录并加在到内存中,然后开始执行引导纪录的代码。至于是否必须加载到0x7c00h,我不认为有这个要求,应当只要加载到没有被占据的内存空间就可以了。

  是不是因为编译器要在程序里设置一些“绝对地址”的跳跃?
  orig这条指令是告诉联接器把它加载到内存的0x7c00h的位置上。

所有上面的一系列操作,都是处于实模式状态下,这时x86处理器仅仅相当于一个8086处理器,所使用的地址都是物理地址,允许访问的存储空间是
1M内存。

我们平时用C写程序 
这些程序的启动地址又是多少呢? 
这个地址是由谁、在哪里设置的呢?

你如果使用的不是纯dos的话,就处在保护模式状态下,这时候,使用的地址都是虚地址,其入口地址是由连接器确定的,应当是一个操作系统下的程序都一样,但执行时被映射到不同的物理页面上去。


 _z_ 回复于:2005-09-21 15:26:47
[quote:f4e608d9e1="renstone921"]至于是否必须加载到0x7c00h,我不认为有这个要求,应当只要加载到没有被占据的内存空间就可以了。[/quote:f4e608d9e1]

默认就是这样的。。。 :em19:  :em19:


 renstone921 回复于:2005-09-21 15:29:57
to _z_:
你说的默认是指什么东西的默认?


 _z_ 回复于:2005-09-21 15:35:29
0x7c00


 renstone921 回复于:2005-09-21 15:39:08
我的意思是跟操作系统相关还是bios具体有什么要求?


 _z_ 回复于:2005-09-21 15:44:57
理解错误 :em19:  :em19:


 wenuy 回复于:2005-09-21 17:46:38
很好玩`~`


 Solaris12 回复于:2005-09-21 22:09:52
[quote:6957955995="renstone921"]我的意思是跟操作系统相关还是bios具体有什么要求?[/quote:6957955995]

应该是PC体系结构的要求吧,可以查查相关规范

不同的arch肯定不一样


 mik 回复于:2005-09-22 12:14:33
[quote:c89f4ff3ca="1jjk"]

不仅仅是汇编!感觉那本书写的很好,因为我这么菜的菜鸟都能看懂!那其他有点功底的前辈就更不用说了,是吧?[/quote:c89f4ff3ca]


那本书开头似乎有点乱。:)


 1jjk 回复于:2005-09-22 12:16:26

是啊
讲的一般是费话
结合linux内核完全注释看看就可以了


 mik 回复于:2005-09-22 12:20:11
[quote:d2e91ac21c="bleem1998"]请问第一句是什么意思呢
是说程序从07c00h开始运行?
还是别的意思?[/quote:d2e91ac21c]


个人认为: 一个bin,即纯汇编语言编译出来的文件,就等于内存的映象。

org 07c00h 指示代码从内存的 07c00h 开头。

power on -> BIOS -> jmp disk boot sector -> jmp 07c00h


 mik 回复于:2005-09-22 12:22:33
[quote:a78f457256="1jjk"]?
是啊
讲的一般是费话
结合linux内核完全注释看看就可以了[/quote:a78f457256]


不是费不费话的问题,而是没将道理讲清楚!

你看过后:
(1)protected mode 寻址弄明白吗?
(2)怎么进入proctected mode 弄明白没?

明白了,说一说看(别照看说) :)


 1jjk 回复于:2005-09-22 12:25:31
呵呵
第三章说了啊

像皇帝更替一样的


 1jjk 回复于:2005-09-22 12:26:05
正在看那一章呢!


 mik 回复于:2005-09-22 13:00:46
[quote:05c9b3adb2="1jjk"]正在看那一章呢![/quote:05c9b3adb2]

我看了一下这本书,有点模糊,没看了,不过 pretected mode 是参考其本才能弄明白。

IA-32  的 protected mod 分页内存管理模式大概这样的:

(1) 逻辑地址 到 线性地址  
                                                                                  线性地址
cs       :         ip                                                  _____________
  ||                  ||                                                 |____________|
0018   :      000A --------- + ----------------           |                        |
  |                                   ________ _      |---->  | offset(000A)   |
  |                                  |_________|                |                        |  
  |---------------->  0018  |_ _______| ---------->|____________|
                                     |_________|                |                        |
                                         ^                              |____________|
      GDTR      _________ _|


(2) 线性地址 到 物理地址 (如果分页管理的话)
如果启用分页机制的话,就经过这步,无分页机制的话,线性地址也就是物理地址。
           线性地址
    _______________________
      |______|________|_______|
      10 bit     10 bit        12bit   (offset)
           |              |               |
           |              |               |_________________ + ____
           |              |__________________                          |
           |                                                   |                         |     
           |                          __页目录___      |                         |    ______
           |___________> |_________|  ---|---> _______   |_>|         |
                                      |_________|     |       |______|        |          |
                                      |_________|     |-->  |______|  --->|           |
                                      |_________|             |______|         |____  |
                                             ^                           页表           物理地址
                                             |
                                             |
                                      CR3  寄存器



 图表乱了些,




弄明白了这些后,看那本书就好看多了。

real mode -> protected mode:
(1) 首先,要准备 GDT 
     自已定义一些值,装入GDTR。(也就是段描述符)
    这些值是 64 位的。
(2) 设置选择子
     将 cs,ds,cs,gs等设为 自定义的 GDT表项。
(3)  设置属性
      cs,ds,cs,gs,及 段描述符 初始化。
(4)开启保护模式。
     置 CR0 的 pe 位,启动保护模式。
(5)jmp 保护模式
      跳转保护模式
      jmp cs段描述符值:0


不知说得对不对:)


 1jjk 回复于:2005-09-22 13:06:08
恩,确实没楼上的兄台说的这么详细!
他没说第二钟
但是之前他说了,不可能全学,只要学自己能用到的就OK了!估计这个也是他没写的那么清楚的原因


 mik 回复于:2005-09-22 13:09:14
[quote:c03a16e6ac="1jjk"]恩,确实没楼上的兄台说的这么详细!
他没说第二钟
但是之前他说了,不可能全学,只要学自己能用到的就OK了!估计这个也是他没写的那么清楚的原因[/quote:c03a16e6ac]

real mode -> protected mode: 
(1) 首先,要准备 GDT 
    自已定义一些值,装入GDTR。(也就是段描述符) 
   这些值是 64 位的。 
(2) 设置选择子 
    将 cs,ds,cs,gs等设为 自定义的 GDT表项。 
(3)  设置属性 
     cs,ds,cs,gs,及 段描述符 初始化。 
(4)开启保护模式。 
    置 CR0 的 pe 位,启动保护模式。 
(5)jmp 保护模式 
     跳转保护模式 
     jmp cs段描述符值:0


 1jjk 回复于:2005-09-22 13:13:07
不知道
没接触64位


 mik 回复于:2005-09-22 13:17:30
[quote:ed5274c7b3="1jjk"]不知道
没接触64位[/quote:ed5274c7b3]

晕倒,这个 64 位 并不是你想的 64 位机的概念

这个 64 位是内存中的 64 位, 也就是 8 个 bytes 的概念

意思是,设置 8 bytes 的属性,分别对应什么


 murdoc 回复于:2005-09-22 13:17:49
我以前买过一本,《linux0.01内核分析与操作系统设计》卢军写的,里面的程序几乎没有注释,实在看不下去,特别是汇编,一片一片的头晕


 1jjk 回复于:2005-09-22 13:23:20
(2) 设置选择子 
   将 cs,ds,cs,gs等设为 自定义的 GDT表项。 
(3)  设置属性 
    cs,ds,cs,gs,及 段描述符 初始化。 
(4)开启保护模式。 
   置 CR0 的 pe 位,启动保护模式。 
(5)jmp 保护模式 
    跳转保护模式 
    jmp cs段描述符值:0


这个有印象
前面的那个好象是32不是64啊


 renstone921 回复于:2005-09-22 13:27:32
第一条前应当加一条
  初始化中断描述符表,使其包含至少前32种中断类型的有效中断门.

多任务系统还应当涉及到任务状态寄存器的使用.


 1jjk 回复于:2005-09-22 13:28:27
第三章我得好好的研究研究,呵呵
我看了两遍第三章的前两节,还是很模糊!
mik  前辈
有没有比较好的相关资料啊?


 mik 回复于:2005-09-22 13:36:06
[quote:29d69e633c="renstone921"]第一条前应当加一条
  初始化中断描述符表,使其包含至少前32种中断类型的有效中断门.

多任务系统还应当涉及到任务状态寄存器的使用.[/quote:29d69e633c]


结合上下文嘛,我们所讨论是只是初步时候,没有深入讨论

初始化 中断描述符,应该是系统初始化时候


 mik 回复于:2005-09-22 13:37:19
[quote:74892c87b3="1jjk"](2) 设置选择子 
   将 cs,ds,cs,gs等设为 自定义的 GDT表项。 
(3)  设置属性 
    cs,ds,cs,gs,及 段描述符 初始化。 
(4)开启保护模式。 
   置 CR0 的 pe 位,启动保护模式。 
(5)jmp 保护模式 
 ..........[/quote:74892c87b3]


段描述符是 8 bytes 的,你回去看一看


 1jjk 回复于:2005-09-22 13:38:02
[quote:d880dd52b0="renstone921"]第一条前应当加一条
  初始化中断描述符表,使其包含至少前32种中断类型的有效中断门.

多任务系统还应当涉及到任务状态寄存器的使用.[/quote:d880dd52b0]


这个在linux源代码里有说


 mik 回复于:2005-09-22 17:21:49
[quote:1c5d746061="1jjk"]第三章我得好好的研究研究,呵呵
我看了两遍第三章的前两节,还是很模糊!
mik  前辈
有没有比较好的相关资料啊?[/quote:1c5d746061]


建议,你先搞清楚 IA-32 结构体系,然后,看这些书,就相当容易了!

:)


 1jjk 回复于:2005-09-22 17:33:02
恩,接受建议


 mik 回复于:2005-09-22 17:35:47
[quote:6150bdc6df="1jjk"]恩,接受建议[/quote:6150bdc6df]


呵呵...

现在,我要搞一套X86-64结构体系来看看,

赶赶潮流,不要落后了


 1jjk 回复于:2005-09-22 17:44:41
呵呵
我是越古董越想玩
新的好象没啥意思
先把原理弄明白再说
建议是接受,但是那个东西一定还是要继续看的
是吧?


 mik 回复于:2005-09-22 17:45:33
[quote:f386295bb5="1jjk"]呵呵
我是越古董越想玩
新的好象没啥意思
先把原理弄明白再说
建议是接受,但是那个东西一定还是要继续看的
是吧?[/quote:f386295bb5]


你看到哪了?


 1jjk 回复于:2005-09-22 17:46:33
第三章
linux源代码全看完了
没注释的一便
注释的一片
看玩归看完
有些概念还是很模糊


 mik 回复于:2005-09-22 17:51:18
[quote:b46bfe63b0="1jjk"]第三章
linux源代码全看完了
没注释的一便
注释的一片
看玩归看完
有些概念还是很模糊[/quote:b46bfe63b0]


linux 源代码你全看完了?


 1jjk 回复于:2005-09-22 17:53:54
不能这么说
看了全看明白
就知道printf是咋来的了


 1jjk 回复于:2005-09-22 17:56:31
看了这么多本书
总结一句话

没有看不懂的书


 1jjk 回复于:2005-09-22 17:57:34
我就是不服这个事
所以以前C语言
谭浩强,张基温 唐永言 写的那本C
我看了N遍


 mik 回复于:2005-09-22 17:57:57
[quote:d432897c7c="1jjk"]不能这么说
看了全看明白
就知道printf是咋来的了[/quote:d432897c7c]

你看了多长时间?

printf() 是咋来的?


 1jjk 回复于:2005-09-22 18:05:40
呵呵
printf函数就是那么来的啊

我发过的

看了2年
88
我吃饭去了


 mik 回复于:2005-09-22 18:08:32
[quote:3719d5e91e="1jjk"]呵呵
printf函数就是那么来的啊

我发过的

看了2年
88
我吃饭去了[/quote:3719d5e91e]

呵呵..

就这么来的,变出来的..


 1jjk 回复于:2005-09-22 18:26:40
呵呵

可变参数

是先看printf
vsprintf
write


 mik 回复于:2005-09-22 22:11:05
[quote:77b2fa1e51="1jjk"]呵呵

可变参数

是先看printf
vsprintf
write[/quote:77b2fa1e51]


看完了 Linux 一定懂不了少。。呵呵


 1jjk 回复于:2005-09-22 22:12:46
拉倒吧
看完了啥也不懂!
连啥是CC都不知道
把我弄得
原来CC是一个比较流行的ddos工具

我一直以为是gcc呢
呵呵(搞笑性质的)

LUPA社区系统帐号.转贴文章之用.
这应是内核区第一贴吧,纪念一下吧.
发新话题