OS作り 再開
しばらく サボっていましたが
また、再開したいと思います。
ストリング命令
アセンブラの入門書だと、ほとんどが
2進法だ16進法だ、レジスタがどうとかこうとか
あまりに基本的な解説が始まり、それで半分終わってしまう。(うんざりですね)
ここでは、これらは飛ばします。 自分で勉強してください。
とても詳しくて、お勧めなHPとして
http://hp.vector.co.jp/authors/VA000124/index.htm
の中の 「アセンブラ入門」 とても良く出来てます。
ここで、基礎は自習してください。
・・・・・・・・・・・・・・・・・・・・・・・・・・・
通常の?CPU 例えば Z80のような単純?な物と比較して
x86系のCPUには ストリング命令 なる
特殊な、そして便利な命令があります。
いきなり、そこまで飛びます。
【基本】
文字列を一度に書き込んだり、比較できる命令です。
① MOVES*,LODS*,STOS*,CMPS* INS* OUTS* の6種類の命令あり。
*はB(バイト単位)、W(ワード)、D(ダブル・ワード)
② REP 命令を頭につけて繰り返し。(繰り返し回数はCXで指定)
③ CLD,STD命令で、プラス方向かマイナス方向かを事前に指定。
(通常は CLD:プラス方向がほとんどでしょうが)
④ データ元(ソース)は DS:SI で示す。
データ先(ディスティネーション)は ES:DI で示す。
【応用】
・REP MOVSB で 文字列のコピーに使える。
・REP STOSB で 文字列のクリアに使える。(全て ALの値で埋める)
・REPNE SCASB で 文字列内から文字を探すのに使える。
・REPNE CMPSB で 文字列同士の比較に使える。
・LODS は使い道がわからない???
【サンプル】
cld 'DF=0 プラス方向
mov si,offset SOURCE 'ソースにある文字列を
mov di,offset DIST
mov cx,8 '8文字
rep movsb 'DISTへコピー
:
SOURCE db "1234ABCD"
DIST db 10 dup(0)
これを踏まえて、OSのコマンドを追加するに当たって
1文字づつ、アスキーコードで比較していたのでは、非常に判り辛いので
わかりやすく、文字列比較で行えるようにプログラムを変更する。
その上で、ファイルの内容を画面に表示する TYPEコマンドを
追加してみます。
COMファイルの構造
ここで、COMファイルの詳細を調べておきます。
MS-DOSで実行可能な COMファイル は、
64Kバイトまでのメモリしか使えないが、単純で
セグメントを意識せずにプログラムが作れます。
特徴としては、
- 100hからロードされ、実行される。
- 先頭部分に PSP*1 と呼ばれる領域がある。
- セグメントはすべて同じ値。(これは当然ですね)
- IPは 100h、SPは FFFEh で開始される。
- スタックの最初(FFFEh,FFFFh)には0hが入っている。(RETすると0番地へ飛ぶ。)
完全に MS-DOS互換を目指すなら、
この PSP の中身をOSがセットしてあげないといけないって事です。
00、01h: INT20hのコード CDh、20h (プログラムの終了処理。) 02,03h: 最大メモリセグメント 使えるメモリが7_FFFFhなら 8000hが入る。 04h: 固定値 00h? 05〜09h: MSDOS.sysへのFAR CALL CP/Mとの互換のためのもの(使っていない?) 0A〜0Dh: プログラム終了アドレス。 (セグメント、オフセットの順)INT22のコピー 0E〜11h: プログラム中断アドレス。 INT 23hのコピー。 12〜15h: 致命的エラーの処理アドレス。 INT 24hのコピー。 16h〜 空き 2C、2Dh: 環境設定?(Path=文字等)へのセグメントアドレス。 2Eh〜 空き 50,51h: INT21hのコード CDh、21h 52h: RETFのコード CBh プログラムから call 50h でも ファンクションコールができるようにしている。 でも、ここも使っているプログラムはほとんど無いような気がする・・・ 53h〜 空き 5C〜6Bh: 第1FCB(16バイト) FCB*2は本来32バイト必要?のはず。 6C〜7Fh: 第2FCB(20バイト?) COMコマンドのパラメータ1,2のFCBがセットされる。 80h: COMコマンドのパラメータの文字数 81h〜FFh: パラメータ文字列(0Dhで終端)
この PSPは EXEコマンドでも同じ構造で、プログラムの先頭に用意されます。
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Hello.com を動くようにする
MS-DOSでは INT 21h (AH=機能番号)
でほとんどの機能を実行しています。
初期の頃に作った
Hello.com プログラムでは、
INT 21h の内の
機能番号 機能
の 3つの機能を使っています。
これをまずは作ってみましょう。
同じ機能が BIOS にもあります。 手を抜いてこれを使ってしまいましょう。
INT 16h が BIOSのキー入力。(AH=00h)
戻り値: AL=アスキーコード、 AH=スキャンコード または
AL=0 なら AH=拡張キーコード
キーコードの詳細表は、OADGリファレンスに載ってます。
さて、先の HeboOSの ソースに少し手を加えて、再アセンブル。
FDにイメージを書き、さらに Hello.com をFDにコピーして
起動します。
>dir で Helloファイルも見えますね。
>Hello
MS-DOSプログラム Hello.com を動かしてみた証拠が上の写真です。
(暗くて見えづらいですが・・・)
その、ソースリストが ↓ です。
id:yang2005:20050103
DOSやWin上で起動したのと同様、画面に”Hello!”と表示され、
何かキーを押すと、OSに戻ります。
ベクタMAP
x86の(というか,AT互換機の)割り込みの資料はここを参考に!
↓
http://www.asahi-net.or.jp/~WR7S-NKMR/BeOS/Documents/IRQ.html
ここなら、一覧表になってます。
↓
http://www.ctyme.com/intr/int.htm
AT互換機は、
INT 00h〜FFh の 256個に対して、幾つかはハードウェアに割り付けられています。
- INT 00-07 例外ハンドラ (内 INT 02h は NMI)
- INT 08 IRQ0 システムタイマ
- INT 09 IRQ1 キーボード
- INT 0A IRQ2 次の割り込みコントローラ②へ接続される
- INT 0B IRQ3 シリアルポート(COM2/COM4)
- INT 0C IRQ4 シリアルポート(COM1/COM3)
- INT 0D IRQ5 ISAサウンドカードなど
- INT 0E IRQ6 フロッピーディスクコントローラ
- INT 0F IRQ7 パラレルポート
ここが、ソフトウェアで利用可能。 INT 10h〜INT 6Fh
その先頭の方は、BIOSで使われています。
ただし、すでに BIOSで使っている所は、私たちが使えない。(使わない)
また、INT 21h以外でも、古いMS-DOSでは、次のINTも使ってしまってます。
- INT 70 IRQ8 リアルタイムクロック
- INT 71 IRQ9 割り込みコントローラ①(IRQ2)からのデージーチェーン。
- INT 72 IRQ10
- INT 73 IRQ11
- INT 74 IRQ12 PS/2マウス
- INT 75 IRQ13 数値演算コプロセッサ
- INT 76 IRQ14 Primary IDEコントローラ
- INT 77 IRQ15 Secondary IDEコントローラ
この先も、ソフトウェアで利用可能。 INT 78h〜INT FFh
この資料から、INT 40h〜6Fh 当たりが安全に使えそうです。
●の部分、INT 21hを、
DOSのファンクションコールと互換性のあるようにプログラムを作れば
DOS用に作られた COMプログラム程度は動くようになるはずです。
別に 自作の独自OS なんで、DOS互換にしなくてもいいんですが、
画面表示やキー入力ぐらいは、互換性があったほうがデバッグしやすい。
HeboOSでは、独自の INT 80hを使おうとしているので
80h * 4 = 200h に オフセット、202h(から2バイト)にセグメントを
書き込んでいます。
INT 21hだと、
21h * 4 = 084h に オフセット、086h(から2バイト)にセグメント
を書けば良いはずです。
まずは、簡単な DOS互換のシステムコールを作って、
前に作ったDOS用のプログラム(ここ→ id:yang2005:20050526 )
Hello.COM
が、手作りOSで、動くようにしてみましょう。
メモリMAP
PC/AT互換機(あえてDOS/V機とは呼ばない事!)の
メモリMAPを調べてみます。
OSDev で かなり詳細に調べてますね!
ここはいつも参考になる。 素晴らしい!!
↓
http://community.osdev.info/index.php?%28AT%29memorymap
ちなみに、LINUXはこんな感じ。↓ (90000hから使っている?)
http://www016.upp.so-net.ne.jp/e17/lb/setupAT.html
アドレス | 内 容 | 説 明 |
_0000h〜_03FFh | 割り込みベクタ | 4バイトづつ、(セグメント+オフセット)×256個。 |
_0400h〜_7BFFh | 30.72Kバイトの空き? | 使ってもいいのかな? |
_7C00h〜_7DFFh | 512バイト。 | ●ここにブートプログラムが読み込まれる。 |
_7E00h〜_7FFFh | 512バイト。 | ここもブート用に使って良いのでは? |
_8000h〜9_FFFFh | 622.592Kバイト。 | ここが自由に使えるRAM領域(ここまでで640KB) |
A_0000h〜B_FFFFh | 画面表示用ビデオRAM | ここに書き込むと画面に表示される |
C_0000h〜F_FFFFh | ビデオBIOSとか、いろいろ | ここは使わない方が無難 |
10_0000h〜EF_FFFFh | 使えるRAMの可能性大。 | チェックしてから使用。(ここから先が、A20問題) |
F0_0000h〜FF_FFFFh | 使えるない可能性あり。 | チェックしてから使用。 |
100_0000h〜無限大 | 実装されている場合に限り・・・ | もう少し、大人になってから使ってみます。 |
ここで重要なのは、●の 7C00h〜 です。
ここに、FDやHDから、最初のプログラムが読み込まれ実行されるようです。
では、なぜ、こんな中途半端な 7C00h なんでしょう?
私が想像するに、
最初にAT機を(のBIOSを)開発した技術者が、
① 1クラスタ(512バイト)もあれば、IPLローダぐらいは書けるだろう!
② それでも足りなくなるとか、1クラスタが1024になったら困るんで、
もう1クラスタ(合計1024バイト)あいてれば、十分だろう?
③ IPLで OSを 0400h〜に読み込ませれば・・・
④ 0400h〜7BFFh(約30KB)もあれば、OSには十分なはず?
↑
この考えが甘いな(笑)
⑤ そうすれば、7C00h〜7FFFhも OS用に使えて無駄にならないし、
(最悪、OS用のスタックとして使ってもOK)
⑥ これなら、8000h〜は、アプリケーション用として、すっきり使える。
(私って、天才!!)
っと、こんな風に考えたんだと思います。
よって、そっくりそのまま踏襲しようと思います。
OSの容量が32Kバイトを超えないうちは・・・
への未練
TASMの使用を あきらめるには、いまひとつ
踏ん切りがつかず、文法の違いを明らかにするためにも
TASMで書き直してみました。
以下が、TASMのアセンブラでエラーなく通るソースです。
しかし、日記に全ソースを公開するのは、無謀かな?
とにかく、長いなー。
何かボタンを押したら表示されるような機能が ハテナにないかな?
ボタンを押したら、ダウンロードできる機能でもいいんだが・・・
↓
あまりに、ソースが長くて、日記が見づらくなるんで、
ここにリンクをはりました。 クリックすると見れます。
id:yang2005:20050102