2017.2.25
前へ
次へ
ホームページトップへ戻る

マイコン独立大作戦
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

前へ
次へ
ホームページトップへ戻る