ブートで遊ぼっ!(4)

86系のPCをブートさせて遊んでみよう、というお話の4回目になります。テキストは『OSを書く:初歩から一歩ずつ』です。
環境はAMD64+Windows10+VMware Workstation 17 Player+Debian 12.4です。
一応前回まででテキストの本文(?)については触れたので、今回からは練習問題について書いてみようかと思います。
まずは練習問題の1番です。

画面に他のものをプリントする。

これ、ものすごく面白い問題だなぁと。といいますか「他のもの」ってのが曖昧過ぎるなぁ。いろんな解釈が出来そう…。
思いつくままに作ってみましょう。

別の文字をプリントする。

これは簡単ですね。文字列の定義を変えるだけです。なのでこんな感じ。

; boot.asm

mov ax, 0x07c0
mov ds, ax

mov ah, 0x0
mov al, 0x3
int 0x10

mov si, msg
mov ah, 0x0E

print_character_loop:
lodsb

or al, al
jz hang

int 0x10

jmp print_character_loop

msg:
db 'Hello, x86!', 13, 10, 0

hang:
jmp hang

times 510-($-$$) db 0

db 0x55
db 0xAA

PlayWithBoot.3.1

実行すると、こう。

文字列を追加してみる

さすがに前節で「練習問題クリア!」とかいうのは何なので、文字列を追加して2つの文字列を表示してみます。これも難しくないですね。
ドカンとコピペして該当箇所をちょこっと変えます。
こんな感じ。

; boot.asm
mov ax, 0x07c0
mov ds, ax

mov ah, 0x0
mov al, 0x3
int 0x10

mov si, msg
mov ah, 0x0E

print_character_loop:
lodsb

or al, al
jz print_2nd_character

int 0x10

jmp print_character_loop

print_2nd_character:
mov si, msg2
mov ah, 0x0E

print_character_loop2:
lodsb

or al, al
jz hang

int 0x10

jmp print_character_loop2

msg:
db 'Hello, World!', 13, 10, 0

msg2:
db 'Hello, x86!', 13, 10, 0

hang:
jmp hang

times 510-($-$$) db 0

db 0x55
db 0xAA

PlayWithBoot.3.2

22行目から34行までがコピーした部分です。設定する文字列のアドレスだけ変更してます。39行目と40行目は追加した文字列の定義ですね。
実行するとこう。

サブルーチンにしてみる

一応、練習問題としてはクリアなのかもしれませんが、ソフトウェアを作る立場としては、ほとんど同じで少しだけ違うコードって気持ちが悪いわけです。
こういう場合、どんな言語でも処理を共通化して、呼び出す形にします。
今回もそうしてみましょう。axに表示したい文字列のアドレスを指定して、サブルーチンを呼び出します。
こんな感じ。

; boot.asm
;
mov ax, 0x07c0
mov ds, ax

mov ah, 0x0
mov al, 0x3
int 0x10

mov si, msg
call print_character

mov si, msg2
call print_character

jmp hang

; sub routine
;
print_character:

mov ah, 0x0E

print_character_loop:
lodsb

or al, al
jz print_character_end

int 0x10

jmp print_character_loop

print_character_end:

ret

; define messages
;
msg:
db 'Hello, World!', 13, 10, 0

msg2:
db 'Hello, x86!', 13, 10, 0

; end of proccess
;
hang:
jmp hang

times 510-($-$$) db 0

db 0x55
db 0xAA

うん。すっきりしました。
実行するとこう。前と変わらないですね^^;
(というか変わったら困ります。それはバグです。)

数値を表示してみる

さて、今までは文字を表示していたんですが、『別のもの』を『文字列でないもの』と解釈することもできるわけです。実際『レジスタの中身を見たい』とか、数値を表示したくなるわけで。例えば数値の1を表示したいとか。
なにも考えずに書いたソースがこれ。

; boot.asm
;
mov ax, 0x07c0
mov ds, ax

mov ah, 0x0
mov al, 0x3
int 0x10

mov ah, 0x0E
mov al, 0x01
int 0x10

; end of proccess
;
hang:
jmp hang

times 510-($-$$) db 0

db 0x55
db 0xAA

PlayWithBoot.3.3

実行すると、こうなります。

あらまぁ、望んだ結果にはなりませんでした。
表示したいのは1で、表示できるのは”1″なんですよね。
文字の”1″を指定してあげないと1は表示されません。
結論から言うと文字の”1″は文字コード(これは数値です)の0x31になります。
なのでソースはこうなります。

; boot.asm
;
mov ax, 0x07c0
mov ds, ax

mov ah, 0x0
mov al, 0x3
int 0x10

mov ah, 0x0E
mov al, 0x01

add al, 0x30

int 0x10

; end of proccess
;
hang:
jmp hang

times 510-($-$$) db 0

db 0x55
db 0xAA

PlayWithBoot.3.4

実行してみます。

望み通り1が表示されました。

ここまでやれば、練習問題1はクリアしたと言っていいんじゃないかな。
なので、今回はここまでです。

《2024/5/3 17:07:24》

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です