86系のPCをブートさせて遊んでみよう、というお話の6回目になります。テキストは『OSを書く:初歩から一歩ずつ』です。
環境はAMD64+Windows10+VMware Workstation 17 Player+Debian 12.4です。
今回はテキストの練習問題の4からです。
4. あるメモリアドレスの内容をプリントする
最初の方で文字を表示する時に、ラベルをつけて文字列を定義、ラベルのアドレスを指定して1文字ずつ表示、とかやっていたわけで、ラベルをつけて数値を定義すればいい感じかない?
で、ラベルのアドレスの先を読み込んで…読み込んで?
どうやって?
というのがこの課題でしょう。
例えば
mov ax, _test
とかすると、axには_testのアドレスが入るわけで、あとはその中身を取り出して…取り出して?
どうやって?
というのがこの課題なんでしょう。
今までやってきたように、axとかに入っている値を扱いたい場合は上の書き方をします。で、それをアドレスとしてその中身を扱いたい場合[]で囲います。例えば今回の「_test」のアドレスの中身を取り出したい場合
mov bx, _test
とかして、_testのアドレスを取得した上で
mov byte al, [bx]
とするわけです。1
欲しいのは0x15という値(41行目の_testのあとにdb命令?で定義しています)
alは1Byte。
mov命令は気が利かないので、alが1Byteなんだからbxのアドレスから1Byteだけ読むなんてことをしてくれません。なのでbxのアドレスから([bx])1Byteをalに移送してくれ(move byte alの部分)と指示します。
読み込めたら後は今まで通り、表示するだけ。
; boot.asm mov ax, 0x07c0 mov ds, ax mov ah, 0x0 mov al, 0x3 int 0x10 mov ax, 0x0000 mov bx, _test mov byte al, [bx] mov bx, ax loop: mov dx, 0 mov ax, bx mov bx, 10 div bx mov cx, dx mov bx, ax mov ah, 0x0e mov al, dl add al, 0x30 int 0x10 cmp bx, 0 jne loop jmp hang ; end of proccess ; hang: jmp hang _test: db 0x15, 0x00 times 510-($-$$) db 0 db 0x55 db 0xAA
PlayWithBoot.5.1
実行すると、こんな感じです。
5. BIOSを使ってディスクから何かを読み込んでみる
わたしはここで挫折しかかりました。ディスク読み込みのBIOSコールは調べられたんですが、パラメータが良くわかりませんでした。
ていうか、端的に言って、シリンダー、ヘッダー、セクターが理解できません。
なんか情報が錯綜しているというか、混じりあってる?
その上、ブートでセクタにはパーティションデーブルがあって、パーティションを特定したらFATがあって、みたいな?
お詫びと開き直りをするまで、結構かかりましたとも。ええ。
で、思ったわけです。
あのね?
わたしはディスクから読み込めればいいの!
FATなんて関係ないの!
と。
そもそもブートセクタは読めているわけで(だから動いてるし)、それはheaderが0、cylinderが0、sectorが1(sectorは1オリジンだそうです)以外にあり得ない。
ならば、それはheaderが0、cylinderが0、sectorを2にすれば読めるんじゃない?
さすがに2sectorの1KByteでheaderもcylinderも変わることないでしょ?
そういう予測のもとにソースを書きます。
; boot.asm mov ax, 0x07c0 mov ds, ax mov es, ax mov ah, 0x0 mov al, 0x3 int 0x10 mov bx, 0x200 ; Destination address to read mov ah, 0x02 ; Read Sectors From Drive mov dl, 0x80 ; Drive mov al, 0x01 ; Sectors To Read Count ; mov ch, 0x00 ; Cylinder mov cl, 0x02 ; Sector(starts from 1, not 0) ; set 2. becouse not need MBR mov dh, 0x00 ; Head int 0x13 ; Execute disk read mov si, 0x0200 mov ah, 0x0E loop: lodsb or al, al jz loop_end int 0x10 jmp loop loop_end: jmp hang ; end of proccess ; hang: jmp hang times 510-($-$$) db 0 db 0x55 db 0xAA test: db 'Hello 2nd sector!', 0x0a, 0x0d, 0x00 _padding: times 0x0400-($-$$) db 0
PlayWithBoot.5.2
さて、動かしてみましょう。
こういうのってワクワクしますよねw
はい。無事に動きました。
今回はここまでです。
なんだか、何かをやり遂げた気がします^^
《2024/5/9 1:18:24》
- mov al, [_test]とか書けた気がする…。 ↩︎