升级版的彩色Hello,OS

 

 2013-4-21 21:00

================== 

升级版的彩色Hello,OS

——我对boot.asm的理解

你的HelloOS程序一定是这样的:
 
图片
这个HelloOS很单调,而且屏幕上充斥着“垃圾信息”。

我的Hello,OS这样的:
 图片

是不是比原来的程序高端很多?其实只要经过小小的更改,就可以写出这个彩色的升级版HelloOS。接下来我们一起探究一下如何编写这个程序。

第一步:理解原版的HelloOS

下面将原版boot.asm代码分成几段来说明

1. org 7c00h

 

首先说明启动电脑以后所要做的事情

电源复位

- BIOS 程序被执行

- Boot 内容被执行

有关Boot结构的规则

必须是一个二进制文件(COM format)

必须是512个字节

最后两个子节必须是0xAA55h

被读入内存的地址是7C00h

org指令的作用是根据其指定的偏移量,计算段内数据的各种偏移。即原地址加上org指定的偏移形成数据的实际偏移地址。如果不写org指令,则相当于org 0,即段内偏移地址为0。那么我们为什么把偏移设为7c00h呢?因为我们写的程序是仿照Linux操作系统的内核引导代码,当PC启动时,BIOS会把启动盘的第一扇区加载到内存0x7c00地址处,然后从此地址开始执行,程序使用数据时(例如“HelloOS!”字符串)所用地址与此相关,org指令使得不用反复写偏移地址就能方便的使用数据。

2.  mov ax,cs  

mov ds,ax

mov es,ax

 

mov 寄存器a,寄存器b”这个指令把寄存器b的值赋给寄存器a

CS是代码段寄存器,代码段1org 7c00h指令使得CS = 0x7c00

在代码段2,先将CS的值赋给AX,然后将AX的值赋给了DSDS是数据段寄存器

你可能会有疑问:为什么不直接写mov ds,cs?因为8086cpu不支持将数据直接送入段寄存器的操作,因此先送入AX,然后送入DS

ES是附加段寄存器,这里赋给它与CS相同的值,当要处理两个字符串时,例如比较两个字符串,设置两个段寄存器会使操作更方便,当所处理的字符串在同一段内时,可以让DS和ES相等。我们这里只需要打印一个字符串,只涉及同一段数据,因此ESDS相等

3. call DispStr

jmp $

 

call DispStr相当于push IP然后jmp DispStr,即保存指令指针然后跳转至DispStr标记处,也就是相当于函数调用了,而jmp $是跳转到哪里呢?首先说明一下jmp的跳转方式,即跳转到 (IP) = (IP)+标号地址-JMP指令后第一个字节的地址。这里$表示当前指令的地址,于是跳转的目标地址就等于(IP)(IP)-(IP)(IP),还是当前指令,这就造成了一个无限循环,使得这条指令无限的执行下去。

 

 

 

4. DispStr:

mov ax,BootMessage

mov bp,ax

 

DispStr:是一个标记,表示它下面第一条指令与段寄存器的相对地址。

BootMessage就是代码最下面的BootMessage数据段相对于数据段寄存器DS的偏移地址。BP称为基址指针寄存器,在作数组和字符串运算时,用于存放内存的偏移地址。这里存放了“HelloOS!”这个字符串相对于ES的偏移地址,其实际地址为ESBP

5. mov cx,16

mov ax,1301h

mov bx,000ch

mov dl,0

int 10h

ret

 

4、5这两个代码段的功能将字符串输出到屏幕,INT 10H是由 BIOS 对屏幕及显示器所提供的服务程序

使用 INT 10H 中断服务程序时,先指定 AH 寄存器,该寄存器表示欲调用的功能,而其他寄存器是该功能的一些属性”,当一切设定好之后再调用 INT 10H 即可。

CX:输出到屏幕的字符个数。

AH:AX的高八位,AH的值表示10h号中断的子程序号,我们这里AH = 0x13,是10h号中断的13h号子程序,注意下面各个寄存器所代表的含义是基于AH = 0x13的,若调用其他号子程序,则意义不一定相同。

AL:AX的低八位,表示光标的初始位置以及字符串打印形式,我们这里AL = 1,表示光标跟随移动并且字符串为“charcharchar……”这样的形式(即普通的字符串)。

DH:DX的高八位,表示当前打印的字符所在行号,我们这里DH = 0,即第0行。

DL:DX的低八位,表示当前打印的字符所在列号,我们这里DL = 0,表示字符串的第一个字符从屏幕上0列开始打印。

BH:页号,我们这里BH = 0

BL:当前打印的字符的颜色,这个寄存器可以帮助我们打印出前面展示的彩色字符串,对于原版HelloOS程序,BL = 0x0c,是淡红色,稍后我们会给出它能表示的所有颜色。

ret: 函数执行完毕,返回调用处。

6. BootMessage: db "Hello,OS!"

times 510-($-$$) db 0

 

db表示存储字节型数据,一个字符正好占一个字节的空间。这里的字符串占据了多个字符的空间。

times 510-($-$$) db 0:“times 循环次数 数据”指令表示用某种数据填充数据段,这里$表示当前指令相对于CS的地址,$$表示一个节的开始处被汇编后的地址,我们这里程序只有一个节,因此$$就相当于7c00h510-($-$$)就等于510减去我们的程序长度的到的值。后边db 0表示用字节型数据0填充我们程序后面的位置,即 “HelloOS!” 字符串后面全部为ASCII为0的字符 (NULL) 。

 

 

7. dw 0xaa55

 

dw表示字型数据,0xaa55占据一个字的空间,表示代码段的结尾。

6代码的510-($-$$)中的510与此相关,8086cpu一个字占据两个字节的空间,我们写的启动扇区的程序运行时共占据512字节,510就是有512-2这样得来的。

 

以上终于介绍完了原版的boot.asm,接下来介绍如何使其“升级”为彩色版 :P

 

第二步:彩色的HelloOS

我们需要几个更高级”一点的汇编知识:使用循环语句、使用堆栈和寄存器的加法操作。

1. 使用循环

基本语法的示例:

mov cx,10 ;;循环执行的次数在循环标记前放入CX,这里循环体将执行10

label: ;;循环每执行一次,CX中的值都会减一,直到CX=0时跳出循环

…… …… ;;循环体

loop label

2. 使用堆栈

基本语法的示例:

push cx ;;将CX的值压入栈中

………… ;;注意这里某些指令可能会更改CX中的值

…………

pop cx ;;将先前保存的CX出栈,CX恢复原来的值

3. 寄存器加法

基本语法的示例:

add ax,1 ;;ax=ax+1

我们程序的基本思路是循环打印15"Hello,OS! Created by HaoXin:P"这句话,每句话的颜色不一样,每打印一句话变更一次颜色,我们已经知道BL表示颜色,其颜色表如下:

二进制数

颜色

例子

二进制数

颜色

例子

0000

黑色

black

1000

灰色

gray

0001

蓝色

blue

1001

淡蓝色

light blue

0010

绿色

green

1010

淡绿色

light green

0011

青色

cyan

1000

淡青色

light cyan

0100

红色

red

1100

淡红色

light red

0101

紫红色

magenta

1101

淡紫红色

light magenta

0110

棕色

brown

1110

黄色

yellow

0111

银色

light gray

1111

白色

white

16颜色,但0000这个颜色与屏幕背景色同为黑色,所以我们只打印15颜色。

具备以上知识点就可以了,接下来给出彩色版boot.asm的源代码以及注释:

 

org 7c00h

mov ax,cs   ;cs=07c00h,ax=cs

mov ds,ax ;ds=07c00h

mov es,ax ;es=07c00h

call DispStr ;push IP, jmp DispStr

jmp $ ;infinite loop

DispStr:

    mov dh,0 ;行号,初始为零,从屏幕第0开始打印

mov bh,00h ;页号为0参见前面的讲解

mov dl,0 ;列号为0参见前面的讲解

    mov bl,1 ;颜色,第一种设为0001参见前面的颜色表

    mov ax,BootMessage ;;

mov bp,ax ;;ES:BP = 字符串地址

mov cx,15 ;循环次数

print: ;循环标记

    push cx ;由于打印字符串需要更改CX,我们先保存CX循环计数的值到堆栈

mov cx,80 ;打印长度为80覆盖所有垃圾信息

mov ax,1301h ;子程序AH = 0x13,光标位置AL = 0x01详见前面的讲解

int 10h ;int 10h中断服务程序

add dh,1 ;行号加1,目的是使下一句打印到下一行

    add bl,1 ;颜色号加1换下一个颜色

    pop cx ;出栈,还原CX为循环次数的值

    loop print ;循环

    ret ;函数返回

BootMessage: db "Hello,OS! Created by HaoXin:P"  ;;字节型数据

times 510-($-$$) db '_' ;;填充剩余空间,我们用下划线来代替空字符,^_^

dw 0xaa55 ;;程序结束标志

 

接下来编写你自己的彩色HelloOS

posted @ 2015-02-04 13:21  郝鑫  阅读(182)  评论(0)    收藏  举报