admin 管理员组

文章数量: 1184232

64位操作系统——bootLoader


作者:王赛宇

参考列表:

  • 《一个64位操作系统的设计与实现》
  • 《nasm用户手册》
  • 各种博客

第一部分: 写一个简单的引导程序并且显示一些字符

    org 0x7c00 ; 将程序加载到0x7c00位置,即:指定程序的起始地址
BaseOfStack equ 0x7c00
; 将CS寄存器的段基址设置到DS、ES、SS中
Label_Start:
    mov ax, cs
    mov ds, ax
    mov es, ax
    mov ss, ax
    mov sp, BaseOfStack
; ======  清空屏幕
    mov ax, 0600h
    mov bx, 0700h
    mov cx, 0
    mov dx, 184fh
    int 10h
; ===== set focus ??? 没看懂这是啥意思
    mov ax, 0200h
    mov bx, 0000h
    mov dx, 0000h
    int 10h
; ===== 在屏幕上显示:Start Booting......
    mov ax, 1301h
    mov bx, 000fh
    mov dx, 0000h
    mov cx, 10
    push ax
    mov ax, ds
    mov es, ax
    pop ax
    mov bp, StartBootMessage
    int 10h
; ===== 软盘驱动器复位
    xor ah, ah
    xor dl, dl
    int 13h
    jmp $
StartBootMessage:	db	"Start Boot"
;=======	fill zero until whole sector
	times	510 - ($ - $$)	db	0
	dw	0xaa55

这个程序可以被分为几个部分:

  • 初始化部分: 定义了程序被加载到的地方,以及程序中的常量,并且对所有寄存器进行了简单的初始化
  • 显示部分: 通过 int 10h 的指令,进行了显示方面的一系列处理
  • 软盘驱动器复位:这里我暂时也没搞明白是在干什么
  • 填充部分

简单的汇编知识

在搞明白这些之前,我们需要先学一点简单的汇编:

我们会发现,上面的程序主要是在对一些寄存器进行简单的操作,这些寄存器是: ax,bx,cx,dx 他们是nasm语言的通用寄存器。同时,这些寄存器可以根据高位、低位被划分成: ah,al,bh,bl,ch,cl,dh,dl ,可以理解为: ax = ah << 16 + al 也就是说 ax 是由 ah\al 两个部分拼接而成的。

理解了这一点之后,你往下看,暂时就没有太大的难度了。

int 指令

我们首先来看一下这里的 int 指令,学过组成原理的同学都知道,这里的int就是软件中断,我们这里用到了两种int指令,他们实际上就是调用了BIOS里面的一些固有程序,进行了一些我们期望中的处理,我们来看一下这些 int 分别做了哪些操作:

第一次
; ======  清空屏幕
mov ax, 0600h
mov bx, 0700h
mov cx, 0
mov dx, 184fh
int 10h

这里设置了 ax = 0600h , bx=0700h , cx=0 , dx=184fh ,然后调用了 int 10h , INT 10h 主要执行的是一些与显示相关的操作。我们来看一下这里的操作:

首先来看 ax 寄存器:我们经过划分可以知道: ah = 0x06 al = 0x00 ,这里的ah指示得是执行 INT 10h 相关程序中的哪种操作:当 ah = 0x06 时,执行的是 按指定范围滚动窗口的功能

具体的参数如下:

  • AL=滚动的列数,若为0则实现清空屏幕功能;
  • BH=滚动后空出位置放入的属性;
  • CH=滚动范围的左上角坐标列号;
  • CL=滚动范围的左上角坐标行号;
  • DH=滚动范围的右下角坐标列号;
  • DL=滚动范围的右下角坐标行号;
  • BH=颜色属性。
  • bit 0~2:字体颜色(0:黑,1:蓝,2:绿,3:青,4:红,5:紫,6:综,7:白)。
  • bit 3:字体亮度(0:字体正常,1:字体高亮度)。
  • bit 4~6:背景颜色(0:黑,1:蓝,2:绿,3:青,4:红,5:紫,6:综,7:白)。
  • bit 7:字体闪烁(0:不闪烁,1:字体闪烁)。

这里我们将 AL 设置为了0, 所以实现的是清空屏幕的功能。

第二次
; ===== set focus ??? 没看懂这是啥意思
    mov ax, 0200h
    mov bx, 0000h
    mov dx, 0000h
    int 10h

这里作者给出的代码中写的是 set focus ,我们还是来看一下 ah 的值: ah = 0x02 ah = 0x02 INT 10h 执行 屏幕光标位置的设置功能

  • DH=游标的列数;
  • DL=游标的行数;
  • BH=页码。
第三次
; ===== 在屏幕上显示:Start Booting......
    mov ax, 1301h
    mov bx, 000fh
    mov dx, 0000h
    mov cx, 10
    push ax
    mov ax, ds
    mov es, ax
    pop ax
    mov bp, StartBootMessage
    int 10h

相信大家已经掌握了这套研究的方法了,我们直入主题: 这里执行的是显示字符串的方法,字符串存储在 StartBootMessage 位置,参数如下:

  • AL=写入模式。
    • AL=00h:字符串的属性由BL寄存器提供,而CX寄存器提供字符串长度(以B为单位),显示后光标位置不变,即显示前的光标位置。
    • AL=01h:同AL=00h,但光标会移动至字符串尾端位置。
    • AL=02h:字符串属性由每个字符后面紧跟的字节提供,故CX寄存器提供的字符串长度改成以Word为单位,显示后光标位置不变。
    • AL=03h:同AL=02h,但光标会移动至字符串尾端位置。
  • CX=字符串的长度。
  • DH=游标的坐标行号。
  • DL=游标的坐标列号。
  • ES:BP=>要显示字符串的内存地址。
  • BH=页码。
  • BL=字符属性/颜色属性。
    • bit 0~2:字体颜色(0:黑,1:蓝,2:绿,3:青,4:红,5:紫,6:综,7:白)。
    • bit 3 :字体亮度(0:字体正常,1:字体高亮度)。
    • bit 4~6:背景颜色(0:黑,1:蓝,2:绿,3:青,4:红,5:紫,6:综,7:白)。
    • bit 7:字体闪烁(0:不闪烁,1:字体闪烁)

我们注意到这里执行的是光标移动到字符串尾端位置的写入模式,通过规定cx,规定了字符串的长度。我们尝试加长字符串的长度,但不更改cx会发生什么样的事情:我们将下面的 StartBootMessage 部分更改为:

StartBootMessage:	db	"01234567891011121314151617181920"

随后进行查看,结果如下:

本文标签: 字体闪烁 系统 位置