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》