30天自制操作系统(二)汇编语言学习和Makefile入门
我们继续学习操作系统的相关内容。
; hello-os ; TAB=4 ORG 0x7c00 ; このプログラムがどこに読み込まれるのか ; 以下は標準的なFAT12フォーマットフロッピーディスクのための記述 JMP entry DB 0x90 DB "HELLOIPL" ; ブートセクタの名前を自由に書いてよい(8バイト) DW 512 ; 1セクタの大きさ(512にしなければいけない) DB 1 ; クラスタの大きさ(1セクタにしなければいけない) DW 1 ; FATがどこから始まるか(普通は1セクタ目からにする) DB 2 ; FATの個数(2にしなければいけない) DW 224 ; ルートディレクトリ領域の大きさ(普通は224エントリにする) DW 2880 ; このドライブの大きさ(2880セクタにしなければいけない) DB 0xf0 ; メディアのタイプ(0xf0にしなければいけない) DW 9 ; FAT領域の長さ(9セクタにしなければいけない) DW 18 ; 1トラックにいくつのセクタがあるか(18にしなければいけない) DW 2 ; ヘッドの数(2にしなければいけない) DD 0 ; パーティションを使ってないのでここは必ず0 DD 2880 ; このドライブ大きさをもう一度書く DB 0,0,0x29 ; よくわからないけどこの値にしておくといいらしい DD 0xffffffff ; たぶんボリュームシリアル番号 DB "HELLO-OS " ; ディスクの名前(11バイト) DB "FAT12 " ; フォーマットの名前(8バイト) RESB 18 ; とりあえず18バイトあけておく ; プログラム本体 entry: MOV AX,0 ; レジスタ初期化 MOV SS,AX MOV SP,0x7c00 MOV DS,AX MOV ES,AX MOV SI,msg putloop: MOV AL,[SI] ADD SI,1 ; SIに1を足す CMP AL,0 JE fin MOV AH,0x0e ; 一文字表示ファンクション MOV BX,15 ; カラーコード INT 0x10 ; ビデオBIOS呼び出し JMP putloop fin: HLT ; 何かあるまでCPUを停止させる JMP fin ; 無限ループ msg: DB 0x0a, 0x0a ; 改行を2つ DB "hello, world" DB 0x0a ; 改行 DB 0 RESB 0x7dfe-$ ; 0x7dfeまでを0x00で埋める命令 DB 0x55, 0xaa ; 以下はブートセクタ以外の部分の記述 DB 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 RESB 4600 DB 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 RESB 1469432
ORG 0x7c00表示让程序被装载到内存的0x7c00号地址。
jmp entry相当于C语言中的goto entry,跳转语句。这是因为前面的东西都是起动区和填充内容,不是可执行的代码,因此要跳过这一部分。
MOV语句其实就是一个赋值语句,MOV AX,0 表示C语言中的 AX=0; 这一语句。
AX其实就是一个寄存器。关于寄存器的内容可以见原文:
汇编语言中经常使用寄存器,这是因为寄存器的访问速度会比内存快很多。
其他的详见书本。然后,我们重点讲下putloop部分,这是汇编语言写循环的基本操作。
我们使用C语言写类似的语句一定是这样的:
for(si=msg;*si != 0x00;i++){ //一些输出文字的操作 }
[SI]表示SI号内存的内容,例如[0x220000]表示0x220000号地址的内容。
其实这个语句可以看做是一个指针,汇编的[x]就是C语言中的*x。
就像上图,SI不断向右,指向下一个内存位置并输出这个字符,直到结束。
汇编语言没有for循环语句,只能使用跳转的方式进行。思路是“如果没有到0,就再执行一遍”,再次执行一遍,就是进行跳转,转到putloop的地方继续执行。
后面有个fin,反复执行HLT。HLT是休眠指令。
讲了这样久,终于把汇编程序讲完了。我们下期再见。