现在的位置: 首页 > 技术文章 > 操作系统 > 正文

《自己动手写操作系统》学习笔记(一)

2013年12月13日 操作系统 ⁄ 共 2403字 ⁄ 字号 《自己动手写操作系统》学习笔记(一)已关闭评论 ⁄ 阅读 2,754 次

《自己动手写操作系统》学习笔记目录(持续更新)  http://www.techbulo.com/832.html

 

一直以来自己就想写个操作系统,虽然也看过不少操作系统的书籍,但大多都是讲理论,完全没有教给你这么实现一个操作系统,哪怕他再简单!忽然有一天我发现了一本书《自己动手写操作系统》于渊著,对书中的内容深深吸引,随即买了一本仔细阅读并一边实践,从今天开始我将学习的过程以及遇到的问题一一记录下来,便于日后查阅。

一.今天首先说一下需要用到的工具,包括硬件和软件:

1.硬件

— 一台计算机(Windows操作系统)

— 一张空白软盘(现在电脑几乎没有使用软盘的,可以使用虚拟软盘,见后续章节)

2.软件

— 汇编编译器NASM。最新版本可以在此链接处获得:http://sourceforge.net/projects/nasm

— 软盘绝对扇区读写工具(FloppyWriter.exe)

二.最简单的启动扇区分析


%define _BOOT_DEBUG_ ; 做 Boot Sector 时一定将此行注释掉!
                     ;将此行打开后用 nasm Boot.asm -o Boot.com
                     ;做成一个.COM文件易于调试

%ifdef _BOOT_DEBUG_
 org 0100h ; 调试状态, 做成 .COM 文件, 可调试
%else
 org 07c00h ; Boot 状态, Bios 将把 Boot Sector 加载到 0:7C00 处并开始执行
%endif

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 "Hello, OS world!"
times 510-($-$$) db 0 ; 填充剩下的空间,使生成的二进制代码恰好为512字节
dw 0xaa55 ; 结束标志

先解释几个伪指令:

1.org伪指令


org 07C00h

格式:ORG 数值表达式

其中,ORG(origin)是操作码,不可省略。表达式给出偏移地址值,即ORG语句后的指令或数据以表达式给出的值作为起始的偏移地址。表达式必须是一个可计算得到的正整数,数值范围在0~65 535之间。

ORG伪指令用来指出其后的程序段或数据块存放的起始地址的偏移量。汇编程序汇编时把语句中表达式的值作为起始地址,连续存放ORG语句之后的程序和数据,直到出现一个新的ORG指令。若省略ORG语句,则从本段起始地址开始连续存放。

在大多数情况下,不需要用ORG语句设置位置指针。由于段定义语句是段的起点,它的偏移地址为0000H,以后每分配一个字节,位置指针自动加1,所以每条指令都有确定的偏移地址。只有程序要求改变这个位置指针时,才需要安排ORG语句。通常ORG语句可以出现在程序中任何位置上。

我们知道编译器本身在汇编时对指令的地址计算是相对地址,而对于引导扇区,是按绝对地址执行,那么对于用相对地址编译的执行码就要换算成绝对地址。一般而言,“真实开始执行的引导扇区”都会被BIOS固定装载到07C00h处。

 由于编译器在编译时的地址是从第一行开始用0000h开始相对计算的,而且我们要写的是“引导扇区”程序,所以我们要将下面的代码加载到地址07C00h处,所以我们需要org 07C00h,通过该伪指令,将代码和数据加载到07C00h地址。

如果你对上边的解释还不是很理解,可以看这篇文章《引导程序为什么要org 07c00h》

下面ORG伪指令举个例子:

下列变量定义,并且变量word1的偏移量为0

word1 DW  1234h

byte1  DB   56h

word2 DW  abcdh

org 0001h

byte2  DB  ?

word3 DW ?

byte3  DB  ?

故如下图所示:

ORG伪指令示例

ORG伪指令示例

2、


jmp $

$被称为当前位置计数器

在汇编程序对源程序进行汇编的过程中,使用地址计数器来保证当前正在汇编的指令地址。地址计数器值可用“$”来表示,汇编语言也允许用户直接用“$”来引用地址计数器的当前值,因此,ORG $+5可表示从当前地址开始跳过5个字节存储单元,在指令和伪指令中,也可直接用“$”表示地址计数器的当前值。

 故jmp $进入了一个无限循环

3、


int  10h

int  10号中断

int 10H 是由BIOS 对屏幕及显示器所提供的服务程序。使用 INT 10H 中断服务程序时,先设定 AH 寄存器得值,该值表示欲调用的功用,而其他寄存器的详细说明,请参考下侧文章,当一切设定好之后再调用 int 10H。

在这里我们只详细讲解本程序中的10号中断。由于ah=13,故调用编号为13的功能:即显示字符串。其中ES:BP=串地址,CX=串长度 ,AH=13,当AL=01h时,光标会跟随显示移动。BH为页号,BH=0表示页号为0,BL=0CH,表示属性,即黑底红字高亮。

因此在调用10号中断之前,无非就是对各个寄存器进行初始化。

关于10号中断的其他信息,请参考

     《BIOS INT 10中断功能详解》

4、


times 510-($-$$)  db  0

times:重复指令或数据

times前缀引起指令被汇编多次。其中$$表示是该程序的初始代码段的地址,故该指令将会被执行510-($-$$)次。也就是用0来填充剩下的空间,达到510字节。

5、


dw 0xaa55 ;

引导扇区结束标志

×