上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
∆TOP




先日購入したOS自作入門ですが,すいすい読めるのですが,すいすい読むと全然わけがわからなくなっていくので,時間かけても納得しながら進めることにしました.
とりあえずNASM(x86系アセンブラ)とQEMUを用いることにしました(本ではNASK).
FATファイル・システム概要を参照して,FAT12のブートセクタの書き方を見てみました.
(どうでもいいですが,Cygwinのmake.exeと相性が悪いようです.よって環境変数からCygwinのパスを消しました)

ORG 0x7C00 ; BS_jmpBoot ブートストラップへのジャンプ命令
JMP START ; 0xEB 0x?? 0x90 ショートジャンプ+NOP
DB 0x90 ;

DB "_BOOTIPL" ; BS_OEMName ボリューム名(8バイト)
DW 512 ; BPB_BytsPerSec セクタサイズ 互換性を考えると512バイト (2バイト)
DB 1 ; BPB_SecPerClus 1クラスタあたりのセクタ数 (1バイト)
DW 1 ; BPB_RsvdSecCnt 予約領域セクタ数 FAT12/16の場合互換性を考えると1 (2バイト)
DB 2 ; BPB_NumFATs FATの数.通常は2 (1バイト)
DW 224 ; BPB_RootEntCnt ルートディレクトリのデフォルトエントリ数 (2バイト)
DW 2880 ; BPB_TotSec16 ボリュームのセクタ数 (2バイト)
DB 0xF0 ; BPB_Media メディアタイプ.リムーバブルの場合は0xF0 (1バイト)
DW 9 ; BPB_FATSz16 1個のFATが占めるセクタ数 (2バイト)
DW 18 ; BPB_SecPerTrk トラック当たりのセクタ数.FDの場合シリンダ一周分が18セクタ (2バイト)
DW 2 ; BPB_NumHeads ヘッド数.FDの場合上下面の2ヘッド (2バイト)
DD 0 ; BPB_HoddSec このボリュームの前にあるセクタ数.パーティションを使わないから0 (4バイト)
DD 2880 ; BPB_TotSec32 ボリュームのセクタ数.32ビットだが結局TotSec16と同じ物を指定 (4バイト)
DB 0 ; BS_DrvNum INT 0x13で使われるドライブ番号.フロッピーは0x00(HDDは0x80) (1バイト)
DB 0 ; BS_Reserved1 予約(WinNT用) (1バイト)
DB 0x29 ; BS_BootSig 拡張ブート標識.続く3つのフィールド(下3つ)が存在することを示す (1バイト)
DD 0xFFFFFFFF ; BS_VolID ボリュームシリアル番号 (4バイト)
DB "BOOTIPLTEST" ; BS_VolLab ボリュームラベル (11バイト)
DB "FAT12 " ; BS_FilSysType フォーマット名 (8バイト) BPBでないが利用用途は一体,,

ヘッダはこんな感じのようです.
ブートセクタとして認識させるためには,BPB_BytsPerSecのサイズにかかわらず,0x01FE,0x01FFに0x55,0xAAが来ないといけないようです.
その他もまぁなんとなくわかりました.(一部わからないヘッダがあるけどまぁそのうち...)

そしてコンパイルし,表示メッセージを定番のアレに設定し,起動にトライ.

ブート失敗

なぜだ!!
と思い,よくわからないながらも,"-l"オプションでNASMコンパイルしたリストファイルを見てみました.
55 0000008A 00 TIMES 0x7DFE-($-$$) DB 0 ; 0x7DFE(0x7C00+0x01FE)
56 00007DFE 55 DB 0x55 ; ブートセクタ
57 00007DFF AA DB 0xAA

0x55と0xAAの番地が違う….ここは0x1FEとかにならなければならないハズです.そういえば本に,ORG命令が来ると$の意味が変わる(=プログラムがロードされるメモリ番地になる)ってあったなぁ….
$の意味が変わるというのは,ORGでプログラムの先頭番地を指定してやったら,あとはそこからのオフセットで各行が実行できるから,CPUが理解できるってことでそうなってるんですかね.ORGがなかったら,どこにプログラムが読まれるかとかわからないから,0x7DFE,みたいな絶対アドレス指定(こんな言い方するのか??)をしなくてはいけないんでしょうかね.

ともかく,ブートセクタの最初の番地,0x7C00を引けば,0x7DFE-0x7C00=0x01FEとなってうまく行きそうなので,0x7C00を引いてやり,NASMへ.
55 0000008A 00 TIMES 0x7DFE-($-$$)-0x7C00 DB 0
56 000001FE 55 DB 0x55
57 000001FF AA DB 0xAA


というか,TIMES 0x01FE-($-$$) DB 0で良いですね.
$と$$については,NASMマニュアルの3.5 Expressionsを参照…,してもわかりにくい(汗)ので,日本語バージョンを参照.
$は式を含む行の最初で、アセンブルする場所を表す。無限ループはjmp $とすればよい。
$$は現在のセクションの最初を表す。セクション内でどれくらい離れているかは$-$$とする。

ようは$$がセクタの開始位置,$が現在の位置ってことなんでしょう.

ともかく実行,実行.うまく行きました.

ブート成功

これしきのことでめちゃ苦労しましたが…,やはり実際に動くと嬉しいもんですね.いい気分転換になりました.

しかし,一つ気になるのは,作成バイナリの先頭バイトが,

気になる

と,いわゆるニアジャンプ?になっていることです.本のバイナリはショートジャンプだったんですが….
何で変わったんだろ.まぁそのうちわかるかなぁ.

進捗: pp.31/pp.700(いつ終わるんだ…)


追記
こちらに,
相対アドレスで1バイトであらわせる範囲内のジャンプをショートジャンプ, 2バイトで表す範囲内へのジャンプをニアジャンプという.
(中略)
無条件ジャンプ命令(jmp命令)はニアジャンプになるが,飛び先がショートジャンプの範囲内にあるときは, jmp short labelとすることでショートジャンプに変更することもできる. 実行速度には影響はない(ショートジャンプにしても速くなるわけではない)が,オブジェクトファイルのサイズが微妙に小さくなる.

とありました.
ニアジャンプとなっていた場合,上の画像のようにE9 4E 00 90となってましたけど,0x00(+02)番地が00となっているので,これはショートジャンプの範囲内にあるということだと判断し,JMP SHORT STARTと変更してやってみました.
うまく動作しましたし,実際にバイナリを覗いてみると...

ショートジャンプ

しっかりショートジャンプになっていました.

そういやアセンブラって,番地が後ろになるほど上位桁になるんですねぇ,これ間違えやすいなぁ.
4E00も,数としてみたら004Eってことなのに….
----
* NASM
* QEMU
* FATファイル・システム概要
* 人生をかるくする秘密のバックヤード
* (AT)BIOS - OS-Wiki
∆TOP



















管理者にだけ表示を許可する



| HOME |


Design by mi104c.
Copyright © 2018 WeBlog of Sky color, All rights reserved.


上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。