今日もやるぞ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 = 0x0aAL = キャラクタコードBH = 0BL = カラーコード- 戻り値: なし
- 注: ビープ、バックスペース、CR、LFは制御コードとして認識される
以上を設定して INT 0x10 とすると文字が出ます。
出たよ0x7c00
ここのプログラムでは ORG 0x7c00 と設定していますが、これは
0x7c00 ~ 0x7dff が、ブートセクタが読み込まれるアドレス
だからです。
なんで 0x7c00 なのかは この記事 に詳しく書いてあります。
3 - ブートセクタだけを作るように整理
コードを分割するだけなので略!!!
4 - 今後のためにMakefile導入
とくに難しいことはないので省略!!!(一般生成規則などややこしいものが出てきたら解説入れます)
今日はここまで
お疲れ様でした。また明日!
3日目は こちら