「30日でできる!OS自作入門」を今更ながらやってみる - 2日目
今日もやるぞOSやるぞ
1日目は こちら
2日目 - アセンブラ学習とMakefile入門
1 - まずはテキストエディタの紹介
2 - さて開発再開
また新たな命令が出てきました。
ORG
: 機械語が実行時にメモリのどの番地にロードされるか
例:ORG 0x7c00
で0x7c00
番地からスタート
GAS(GNU Assembly)なんかだとORG
命令がないのでリンカスクリプトで指定してあげます。
こんな感じ↓
SECTIONS { . = 0x7c00; //「.」は現在の番地を表します。 }
JMP
:JMP 0x3cf5
とかJMP loop
みたいな感じで使う
メモリの番地かラベルまでジャンプするMOV
:MOV SS,AX
でSS = AX
と同等の作用(SSにAXを代入)
ゆかいなレジスタたち
16ビットレジスタくんたちです。
AX
: アキュムレータ(累積計算機という意味)
各種演算に使うと効率がいいCX
: カウンタ
回数を数えるときに使うと効率がいいDX
: データBX
: ベース
メモリの番地計算の起点に使うと効率がいいSP
: スタックポインタBP
: ベースポインタSI
: ソースインデックス(読み込みインデックス)DI
: ディスティネーションインデックス(書き込みインデックス)
レジスタには上のような役割があるらしい。何も書いていないものは今はわからないものです。分かり次第追記します。
次は8ビットレジスタくんたちです。
AL
: アキュムレータロウCL
: カウンタロウDL
: データロウBL
: ベースロウAH
: アキュムレータハイCH
: カウンタハイDH
: データハイBH
: ベースハイ
16ビットレジスタに名前が似ているのは、たとえば AX = 0x3c21
だった場合、 AL = 0x21
, AH = 0x3c
のように、 AX
の下位8ビットが AL
に、 AX
の上位8ビットが AH
に入るらしいです。
ところで8ビットの各種演算の時は AL
と AH
のどちらを使うとより効率がいいのでしょうかね?わかったら追記します。
32ビットレジスタとセグメントレジスタの解説についてはまた今度。
メモリは[]で囲もう
NASKではメモリの番地を指定したい場合は次のように書きます。
MOV SI,0x21 MOV AL,[SI]
これは レジスタ AL
に、メモリ SI
番地に保存されている値を書き込みなさい という意味です。今回の場合は 0x21
番地に保存されているデータが AL
に代入されます。
メモリは[]で囲むと良さそうです。
リトルエンディアンで行こう
本によるとどうやらメモリには8ビットずつの塊でデータが保存されるらしいです。ここで問題なのがその保存方式です。こんな感じで保存されます↓
(Wikipediaより)
これはつまり、 MOV [678],0x007f8400
みたいにすると、 678
番地に 0x8400
が、 679
番地に 0x007f
がそれぞれ保存される 、ということです。
この保存方式を巷では「リトルエンディアン方式」なんて言うみたいです。詳しく解説はしないので気になった人はググってください。
INT命令とBIOS
新たな命令です。
INT
: ソフトウェア割り込み命令のこと
これだけだと何がなんだかわかりませんが、今のところはBIOSの関数呼び出しの一種だと思っておけばいいらしいです。
BIOSというのは「basic input output system」の略です。いかにも画面に文字表示したりキーボード入力できそうな雰囲気ですね。これを用いてハロワを表示させていたんですね〜
一文字を表示させるためには以下のように設定すればよいそうです。
AH = 0x0a
AL = キャラクタコード
BH = 0
BL = カラーコード
- 戻り値: なし
- 注: ビープ、バックスペース、CR、LFは制御コードとして認識される
以上を設定して INT 0x10
とすると文字が出ます。
出たよ0x7c00
ここのプログラムでは ORG 0x7c00
と設定していますが、これは
0x7c00 ~ 0x7dff
が、ブートセクタが読み込まれるアドレス
だからです。
なんで 0x7c00
なのかは この記事 に詳しく書いてあります。
3 - ブートセクタだけを作るように整理
コードを分割するだけなので略!!!
4 - 今後のためにMakefile導入
とくに難しいことはないので省略!!!(一般生成規則などややこしいものが出てきたら解説入れます)
今日はここまで
お疲れ様でした。また明日!
3日目は こちら