ディスクからデータをメモリに転送して、それを画面上に表示しただけで「あーもうアセンブリ分かったわー」とか思ったつもりになるのはおかしいと言う事に気が付き、やっぱりアセンブルを継続中。
…と、言うのは今考えた建前で、本当はアセンブルが楽しいのでもうちょっと続けたいと思ったから続けてた。
でも上記の理屈ももっともなので、アセンブリだけでもうちょっと色々出来るようにしてから次のステップに移行しようと思う。
だから当分は使えるメモリは1MB。。と言っても今のところ512バイトすら使いきれてないから全然余裕だが。
文字列表示が出来るようになったので、今度はダンプ表示をしたくなった。
とりあえず[7C00]から512バイト分のデータを画面上に表示したいんだけど、そのままの状態で文字列表示関数に渡すと文字化けしまくりで読めないので、ASCIIコードに変換する処理を挟む必要がある。
と、言うワケで以下のプログラムを書いた。
数値は全て16進数。
;処理するバイト数を指定
mov cx,0200
;初期化
push cx
mov bx,7c00
mov dx,0000
mov si,dx
変換処理:
mov ax,0000
mov bl,dl
mov ah,[bx]
shr ax,1
shr ax,1
shr ax,1
shr ax,1
shr al,1
shr al,1
cmp ah,09
ja 上位アルファベット
add ah,30
jmp 上位代入
上位アルファベット:
add ah,41
上位代入:
mov cl,ah
cmp al,09
ja 下位アルファベット
add al,30
jmp 下位代入
下位アルファベット:
add al,41
下位代入:
mov ch,al
mov bh,80
mob bl,dh
mov [bx],cx
;ループ継続用処理 & 判定
add dx,0201
pop cx
dec cx
cmp cx,0000
jz 終了
jmp 変換処理
終了:
読みやすくするためにアセンブリっぽく書いてあるけど実際は全部機械語で書いた。
debug.exeをアセンブラ代わりに使ってるけど、その使い方は「『mov [bx],cx』って言う機械語はあるのかな?」と思った時に、辞書の代わりとして使ってる感じ。
全部頼りっきりだとエラーが出た時に理由が分からなくて困るだろうから。
だが、全部ハンドアセンブルなんかしてると、やっぱjmpの飛び先を間違えたり、機械語の入力間違いで変な命令になっちゃってる場合もあったりする。
上記緑字のプログラムは意図した通りの結果を生まない。
理由は不明。
機械語の入力ミスを疑って、ハンドアセンブルをやり直したり、ハンドアセンブルした物を逆アセン用ツールで逆アセンして、意図した通りのプログラムになってるか確認したり、jmpの飛び先を検証したけど、間違いは無かった。いや、正確には、あったんだけど全て修正した。
それでも尚うまくいかないので、一つ一つの機能が自分の意図した通りの動作をしてるか検証するために、debug.exeのgコマンドを使おうとした。
例えば「shr ax,1」×4は、ahレジスタに読み込んだ1バイトの情報を右側に4bitずらすつもりで書いたんだけど、今回初めて使うニーモニックなので、本当に出来てるか分からない。
と、言うわけで、debug.exeで以下のプログラムを書いて実行しレジスタの値を確認した。
2D2B:0100 mov ax,0000
2D2B:0103 mov ax,1200
2D2B:0106 shr ax,1
2D2B:0108 shr ax,1
2D2B:010A shr ax,1
2D2B:010C shr ax,1
上記プログラムを実行すると、俺の予想ではaxレジスタの内容が「0120」になってる筈。
俺は「-G 0100 010D」と入力した。
結果は───
AX=1200 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=2D2B ES=2D2B SS=2D2B CS=2D2B IP=0100 NV UP EI PL NZ NA PO NC
予想と異なる結果が出た。
代入は出来てるっぽいが、シフトが出来てない。
……debu.exeに表示されている結果を上記のように書き出している時に気が付いたんだが「IP=0100」になっている。
ちょっとうろ覚えだが、確かIPは「CPUが次に処理するアドレス」だった筈…。
俺は「-G 0100 010D」と書いた。「0100」から「010D」までを実行して欲しかった。
「010D」まで実行したら、次に実行するべきアドレスは「010E」の筈だ。直前の命令がjmpとかじゃなければ。
……とか何とか、よく分からない事を考えて、debug.exeをいじくり回していたら「『-g 0100』と書いたら『0100』の命令だけが実行される。表示されるレジスタの内容は実行前の状態。」と言う事が分かった。
じゃぁ「-g」コマンドの二つ目のオプションは何なんだと思うけど、分からなかった。
とにかくdebug.exeのgコマンドの使い方も分かった。
そしてシフトもちゃんと出来てる事が分かった。
他に新出の命令は無い筈なんだけど、どこが間違っているのだろうか。。
ダンプ表示が出来るようになったら今度は関数を使えるようにしたい。
今は機能単位でプログラムを分けるって事が出来てなくて、数珠繋ぎみたいになっちゃっていて使い勝手が悪い。
pushとpopを使うなりして関数の呼び出し順序とか返り値の保存アドレスとかを決めるべきだと思う。
まぁ、その前にまずはダンプ表示がマトモに出来ないとお話にならないんだけど。
…と、言うのは今考えた建前で、本当はアセンブルが楽しいのでもうちょっと続けたいと思ったから続けてた。
でも上記の理屈ももっともなので、アセンブリだけでもうちょっと色々出来るようにしてから次のステップに移行しようと思う。
だから当分は使えるメモリは1MB。。と言っても今のところ512バイトすら使いきれてないから全然余裕だが。
文字列表示が出来るようになったので、今度はダンプ表示をしたくなった。
とりあえず[7C00]から512バイト分のデータを画面上に表示したいんだけど、そのままの状態で文字列表示関数に渡すと文字化けしまくりで読めないので、ASCIIコードに変換する処理を挟む必要がある。
と、言うワケで以下のプログラムを書いた。
数値は全て16進数。
;処理するバイト数を指定
mov cx,0200
;初期化
push cx
mov bx,7c00
mov dx,0000
mov si,dx
変換処理:
mov ax,0000
mov bl,dl
mov ah,[bx]
shr ax,1
shr ax,1
shr ax,1
shr ax,1
shr al,1
shr al,1
cmp ah,09
ja 上位アルファベット
add ah,30
jmp 上位代入
上位アルファベット:
add ah,41
上位代入:
mov cl,ah
cmp al,09
ja 下位アルファベット
add al,30
jmp 下位代入
下位アルファベット:
add al,41
下位代入:
mov ch,al
mov bh,80
mob bl,dh
mov [bx],cx
;ループ継続用処理 & 判定
add dx,0201
pop cx
dec cx
cmp cx,0000
jz 終了
jmp 変換処理
終了:
読みやすくするためにアセンブリっぽく書いてあるけど実際は全部機械語で書いた。
debug.exeをアセンブラ代わりに使ってるけど、その使い方は「『mov [bx],cx』って言う機械語はあるのかな?」と思った時に、辞書の代わりとして使ってる感じ。
全部頼りっきりだとエラーが出た時に理由が分からなくて困るだろうから。
だが、全部ハンドアセンブルなんかしてると、やっぱjmpの飛び先を間違えたり、機械語の入力間違いで変な命令になっちゃってる場合もあったりする。
上記緑字のプログラムは意図した通りの結果を生まない。
理由は不明。
機械語の入力ミスを疑って、ハンドアセンブルをやり直したり、ハンドアセンブルした物を逆アセン用ツールで逆アセンして、意図した通りのプログラムになってるか確認したり、jmpの飛び先を検証したけど、間違いは無かった。いや、正確には、あったんだけど全て修正した。
それでも尚うまくいかないので、一つ一つの機能が自分の意図した通りの動作をしてるか検証するために、debug.exeのgコマンドを使おうとした。
例えば「shr ax,1」×4は、ahレジスタに読み込んだ1バイトの情報を右側に4bitずらすつもりで書いたんだけど、今回初めて使うニーモニックなので、本当に出来てるか分からない。
と、言うわけで、debug.exeで以下のプログラムを書いて実行しレジスタの値を確認した。
2D2B:0100 mov ax,0000
2D2B:0103 mov ax,1200
2D2B:0106 shr ax,1
2D2B:0108 shr ax,1
2D2B:010A shr ax,1
2D2B:010C shr ax,1
上記プログラムを実行すると、俺の予想ではaxレジスタの内容が「0120」になってる筈。
俺は「-G 0100 010D」と入力した。
結果は───
AX=1200 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=2D2B ES=2D2B SS=2D2B CS=2D2B IP=0100 NV UP EI PL NZ NA PO NC
予想と異なる結果が出た。
代入は出来てるっぽいが、シフトが出来てない。
……debu.exeに表示されている結果を上記のように書き出している時に気が付いたんだが「IP=0100」になっている。
ちょっとうろ覚えだが、確かIPは「CPUが次に処理するアドレス」だった筈…。
俺は「-G 0100 010D」と書いた。「0100」から「010D」までを実行して欲しかった。
「010D」まで実行したら、次に実行するべきアドレスは「010E」の筈だ。直前の命令がjmpとかじゃなければ。
……とか何とか、よく分からない事を考えて、debug.exeをいじくり回していたら「『-g 0100』と書いたら『0100』の命令だけが実行される。表示されるレジスタの内容は実行前の状態。」と言う事が分かった。
じゃぁ「-g」コマンドの二つ目のオプションは何なんだと思うけど、分からなかった。
とにかくdebug.exeのgコマンドの使い方も分かった。
そしてシフトもちゃんと出来てる事が分かった。
他に新出の命令は無い筈なんだけど、どこが間違っているのだろうか。。
ダンプ表示が出来るようになったら今度は関数を使えるようにしたい。
今は機能単位でプログラムを分けるって事が出来てなくて、数珠繋ぎみたいになっちゃっていて使い勝手が悪い。
pushとpopを使うなりして関数の呼び出し順序とか返り値の保存アドレスとかを決めるべきだと思う。
まぁ、その前にまずはダンプ表示がマトモに出来ないとお話にならないんだけど。