マイコン独立大作戦
CRT/VGAIF+KEYIF+SDCARDIFボードの製作
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
WindowsパソコンにUSB接続して使う現行方式はそれなりに便利ではありますが、ときとしてWindows
のしがらみから開放されて、小さいながらも独立した一個のパソコンとして機能したいと思うこともあります。
昔はそれが普通のことだったのですが、安価なCRTディスプレイが生産中止となって久しい今日ではそれ
は叶わぬことと諦めていたのですが…。
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
[総合第17回]
●画面表示テストプログラム(2)
前回はAM188マイコンボードで実行するVGA画面表示テストプログラムの説明をしました。
その中で8086のOUT命令について下のように書きました。
8086のOUT命令ではアドレス指定はDXレジスタしか使えません。
これは舌足らずな表現でした。
正しくは、
8086のOUT命令では16ビットのアドレス指定はDXレジスタしか使えません。
と書くべきでした。
8086のOUT命令は、そのほかに8086やZ80と同じように8ビットのI/Oアドレスを直接指定する
OUT nn,AL
OUT nn,AX
があります。
今までそのことについて書かなかったのには理由がありました。
しかし前回分を書いてしまったあとで8086のOUT命令についてあらためて考えてみましたら、やっぱりこのままいくのはどうにもまずい、という結論になりました。
それで、そのことについては昨日、「16ビットマイコンの製作」[第17回]として訂正記事をUPしました。
そういうことですので、前回お見せしたテストプログラムもOUT命令のところを書き直しました。
2017/2/24 7:225 vgatest3.LST [00001] ;;; display test 3 [00002] ;17/2/24 [00003] ; [00004] ORG=8000 [00005] ; [00006] START=F055 [00007] ; [00008] 8000 B0FF MOV AL,FF [00009] 8002 E6D0 OUT D0,AL [00010] 8004 BB00F8 MOV BX,F800 [00011] 8007 881F LOOP:MOV [BX],BL [00012] 8009 43 INC BX [00013] 800A 81FBD0FF CMP BX,FFD0 [00014] 800E 75F7 JNZ LOOP <8007> [00015] 8010 B000 MOV AL,00 [00016] 8012 E6D0 OUT D0,AL [00017] 8014 EA55F000F0 JMPF F000:START [00018] ; LOOP =8007 START =F055 |
やっぱりこのほうが簡単で使い易いですね。
さて前回の説明の続きということで、8086のJMP命令についてもう少し書いておきます。
8086のジャンプ命令にはここで使っているJNZなどの条件付ジャンプ命令を含めて、8080のジャンプ命令をさらに拡張した多くの命令があります。
8080のジャンプ命令と同じニーモニックの命令もありますが、8080と違って8086のジャンプ命令はアドレス指定が絶対アドレスではなくて相対アドレス指定になっています。
そのことについては前回も書きました。
今回はJNZ命令の機械語コードを例にして、もう少し補足しておきたいと思います。
上のリストのJNZ命令はアドレス8007へのジャンプ命令ですが、機械語コードを見ると、オペランド部は1バイトしかありません。
JNZの機械語コードは75です。
次のF7がジャンプ先アドレスを示しています。
8080では機械語命令コードに続く2バイトで直接ジャンプ先アドレスを示していました。
実はF7という値はジャンプ先アドレスまでのバイト数を示しているのです。
JNZ命令がCPUによって読み込まれたとき、PC(プログラムカウンタ)にはその次のアドレスが入ります。
8010です。
その値にJNZ命令で指定している値を加算することで、目的のアドレスへのジャンプが行なわれます。
その距離を計算してみると
8010H−8007H=9
になります。
JNZ命令よりも前に戻りますから、この場合には−9になります。
8ビットの符号付16進数では−9はF7です。
ジャンプ命令よりも先のアドレスにジャンプするときは正の8ビット16進数が使われます。
ということはJNZなどの条件付ジャンプ命令は8086では+127(7F)から−128(80)の範囲にしかジャンプできないということになります。
条件付ジャンプ命令の多くは比較的短い距離にジャンプすることが多いので大抵の場合はその範囲に収まります。
ただ中にはその範囲外にジャンプする場合も出てきます。
そういうときのためにJMP命令(無条件ジャンプ)だけは8ビットの相対アドレスのほかに16ビットに拡張した相対ジャンプ命令も使えます。
16ビットならば少なくともセグメント内の半分の範囲をカバーしますからこれで大体は間に合います。
このJMP命令と条件付ジャンプ命令を組み合わせることで少し工夫すれば64KB以内のプログラムを書くことができます。
JMP命令には相対ジャンプ命令のほかにレジスタの値を16ビットのジャンプ先アドレスとみなしてそのアドレスにジャンプする命令(たとえばJMP BXのように)もあります。
また64KBを越えるプログラム(セグメント外にジャンプするプログラム)に対しては上のリストの最後にあるJMPF命令(far jamp)が用意されています。
なおJMP命令のジャンプ先距離が+127〜−128の範囲内かそれを越えて16ビットの値になるのかは意識する必要はありません。
当社オリジナルの8086アセンブラは機械語に翻訳する時点で適切に判断して8ビットか16ビットを割り当てます。
以下にその実際の例を示します。
下は「TK−80風」モニタプログラムの一部です。
[00091] ; [00092] ; MONITOR START [00093] ; [00094] F04F BCD0FF START:MOV SP,MONSP [00095] F052 E81D01 CALL SEGCG <F172> [00096] F055 E8E601 START2:CALL LEDDP <F23E> [00097] F058 E85F01 CALL KEYIN <F1BA> [00098] F05B 8AD8 MOV BL,AL [00099] F05D 2410 AND AL,10 [00100] F05F 7411 JZ DIGIT <F072> [00101] F061 80E30F AND BL,0F [00102] F064 8AFB MOV BH,BL [00103] F066 02DB ADD BL,BL [00104] F068 02DF ADD BL,BH [00105] F06A B700 MOV BH,00 [00106] F06C 81C383F0 ADD BX,TABL [00107] F070 FFE3 JMP BX [00108] ; [00109] F072 E8EE00 DIGIT:CALL SHIFT <F163> [00110] F075 A0ECFF MOV AL,[*DATA] [00111] F078 0AC3 OR AL,BL [00112] F07A A2ECFF MOV [*DATA],AL [00113] F07D E8CD00 CALL RGDSP <F14D> [00114] F080 EBCD90 JMP START <F04F> [00115] ; [00116] F083 EB5290 TABL:JMP GOTO <F0D7> [00117] F086 EB5590 JMP RESRG <F0DD> [00204] F142 A3ECFF MOV [*DATA],AX [00205] F145 E80500 ADDSP:CALL RGDSP <F14D> [00206] F148 E904FF JMP START <F04F> [00207] ; |
107行に上で説明したJMP BXがあります。
この命令は8080のPCHL(Z80ではJP (HL))に相当する命令です。
114行にJMP STARTがあります。
機械語コードを見るとEBCD90になっていて3バイトあります。
じつは3バイト目の90はNOP(8080ではコード00)命令なのです。
当社オリジナルの8086アセンブラは使い易さを考えた1パスアセンブラです(アセンブルとリンクを1度で済ませます)。
そのためアセンブルの時点ではジャンプ先が8ビットなのか16ビットなのかが決定できないためジャンプ先のアドレスエリアとして2バイトを確保しておき、リンク時点で8ビットだった場合には上位アドレスのところにはNOP(コード90)を埋めます。
206行のJMP命令は128バイト以上離れているためにオペランドが16ビットになっています。
114行も206行もソース部分は同じJMP STARTであることに注目してください。
CRT/VGAIF+KEYIF+SDCARDIFボードの製作[総合第17回]
2017.2.25upload
前へ
次へ
ホームページトップへ戻る