第四回講義 「文字表示」

はいはい。というわけで、今回の講義からやっと本格的にAssembler Programingというものに入れます。

まぁ、まずはもっとも初歩的且つ重要なUser Interfaceの1つを司る「文字表示」についてを取り扱います。


対象となるDeviceはTextとGraphicです。

今回の講義内容の殆どはTextについてのみですけど、最後の方で少しだけ、Graphicへの表示についても取り上げてみたいと思います。


文字の表示方法には、いくつかの方法があるんですけども、大体を取り上げてみると、以下の通りじろゃないんでしょうか。


No.

手段

コメント

1

MS-DOS Functionを使用

MS-DOS環境では、最も単純且つ容易にできる方法です。

しかし、PC-Engineには標準ではない機能なのだ(^^;

私も、MS-DOS用の開発時には多用しますね。

2

BIOSを使用

実は、PC-Engine上での最も単純な方法がこれ。

98の場合ですと、MS-DOSによる方法を使うんですけど。

VA用の開発時にはこっちをよく使いますね。

3

Text VRAMに文字コードを転送

その昔、初めてAssemblerでSoftを作り始めたとき、使った方法です。

いや、その時はMS-DOS Functionを知らなかっただけなんでけすけどね(^^;

まぁ、個人的には、この方法がHardwareを理解する上では、よい方策だと思います。

ただ、汎用性には欠けますけどね(--;;;;;

4

Graphic VRAMに絵として転送

ここまでくると、結構色々とやり始めている人向けだったりするんです。

G-VRAMっていうのは、極端にHardwareの制約を受けやすい部分なもんですからね。

ちなみに、MS-Winは全部この方法を使っているんですよね(そこまで普段は意識しないけど(^^;)

この方法を使うと、自由な形状の文字が使える分だけ、その管理は全部開発者に任されるわけで、結構面倒くさいですけど、使えるようになると、もの凄く有用な方法なんですよ。


多分これぐらいだと思います。

まぁ、最も私が最終的に推奨する方式は、最後に挙げた方式(G-VRAMに転送)なんですけども、ここまでは今回は少しだけたどり着く程度にしておいて、3つ目までの方法を主として説明していきますね。


さてさて、まず1つ目の方法についてですけど、極々単純なものです。


;Sample Program 1

        Ideal
        P186
        Model   Small
        Stack   0200h

CodeSeg

        mov     ax,@code
        mov     ds,ax
        mov     ax,00900h
        mov     dx,Offset SampleWords
        int     021h
        ret

SampleWords:
        db      'This is Sample Program.',00dh,00ah,'$'

        End


これだけです。簡単でしょ。ちなみに、Control Word(Ascii Codeで00 - 1Fh)を含んでも、Escape Seaquence Codeを含んでもかまわないんです。

つまり、常に同じ行に表示したければ、LF Codeを送信すればいいですし、色を変えたければ、Escape Seaquence Codeを送信すればいいですし・・・。

ただ、難点を1つあげれば、好きな位置に表示するには、ちょっと骨折れというぐらいです(そもそも、1 Line毎の表示を前提としていますので)。

この方法の要点といえば、

だけです。

また、1文字表示というものもありますが、これに関しては取り扱わなくてもいいでしょう。

(詳しくは、別途MS-DOS Functionに関する書籍などを参照してくださいな)


次に、BIOSを用いる方法ですけど、ここではPC-Engineによる方法を説明します。


;Sample Program 2

        Ideal
        P186
        Model   Small
        Stack   0200h

CodeSeg

        mov     ax,@code
        mov     ds,ax
        mov     ax,00200h
        mov     dx,0ffffh
        mov     si,Offset SampleWords
        int     083h
        ret

SampleWords:
        db      'This is Sample Program.',00dh,00ah,000h

        End


やってる事は殆ど変わりませんね。

ただ、Escape Seaquency Codeは送信しても無駄になってまいます(だったはず(--;)。

この方法も1Lineのみの表示を前提としています。

要点は

ですね。

まぁ、この方法はPC-88VAでなければ使用できません。98のBIOSを使う方法は・・・知りません(^^ゞ

最大の難点は、PC-EngineというOSはPC-88VA Seriesのみですので、大抵の機種で採用されているMS-DOSでの方法のような汎用性はなく、VA専用になるというぐらいなんですけども、BIOS自体が各機種毎ということを前提としていますので、本当は汎用性を求めるApplicationには用いることは望ましくない方法なんです。


プログラミング時まめ知識その1−BIOSってなんだろう−


最近では殆ど気にされなくなっているというか、あまり使われることのない用語ですね。

AT互換機では、Boot時にBIOSがCallされて・・・っていうのがありますけど、そういうのとは、ちよっと違う意味なのがここで出たBIOSなんです。

確かに、初期起動時や、色々な機種の内部操舵をするという意味ではおんなじなんですけどね。でも、それを自由に扱えるか、それとも殆ど強制的に使わされるだけなのか・・・っていう違いがあるんです。

ここで述べているのは、前述の方なんですけどね。


さてさて、で、このBIOSというやつなんですけども、言うが早いが、「USERを影ながら補佐してくれるもの」なんですね。

つまり、色々とMachineのDeviceを制御するにも、例えばFloppy Diskとか、CRTとか・・・そんなところまで管理してられませんよね。

で、その管理の大体をひとまとめにして、Macro的にしたのが、BIOSなんです。

幾つかは、USER(Programer)に開放して有益であるものとされるものは、USERに開放されてます。

たとえば、VAなら、INT 70h-にあったり、98ならINT 18hにあったり等。

まぁ、BIOSは、Machineの状態を管理して、殆どの状態でも動作するように設計されていますので、少々処理が遅くなったりするんですけども、Applicationを安全に設計したい場合には、極力BIOSを通すべきかもしれません。

(ただ、中には手抜きなものもあったりしますけど(^^;)

まぁ、使用するDeviceを自分で管理しきれるというのでしたら、下手にBIOSを通して、処理に足かせをかけるよりも、自分でDriverを作成すれば、それにこしたことはないんですけどね。


ちなみに、MS-Winにある、WinAPIも、BIOSみたいなものだと思います。

そういえば、SHARPの電算機では、BIOSという名前ではなく、IOCSという名前でよんでたような・・・


さてさて、では次に、T-VRAMに直接転送する方法について説明しましょう。

まず、この方法の要注意する点としては、Applicationの安全性の管理はすべてProgramerにかせられるという点ですね。

つまり、直接に文字表示を司るDeviceに殆ど一対一対応しているT-VRAMを直接操舵するということは、もし誤ったことをすると・・・当然T-VRAMの表示情報は破壊されますね。

下手をすると、今現在おきていることがわかんなくなってしまいかねません。

つまり、画面に何か文字が色々と出てるはずなのに、それが読めない(わからない)なんて事になってしまいかねないからです。


とはいえ、正しくやれば、全く問題はない方法なんですけどもね。


ではでは、Sample Programを示しましょう。


;Sample Program 3

        Ideal
        P186
        Model   Small
        Stack   0200h

CodeSeg

        push   es

        mov    ax,0a000h
        mov    es,ax
        xor    di,di

        mov    al,031h
        mov    [Word es:di],al

        pop    es
        mov    ax,04c00h
        int    021h

        End


これを実行すると、画面の左上に「1」って表示されるはずです。

ここでやったことは極々単純で、T-VRAMの先頭に1の文字コード31hを転送(書き込み)をしただけなんです。


プログラミング時まめ知識その2−T-VRAMってなんだろう−


VRAMっていうのから、説明しておきましょう。

まず、VRAMというのですけども、Video-RAMの略称です。

内容は、(最近の電算機では)画面に表示する内容(Text(文字)とGraphic(画像))を管理するところです。

(ちなみに昔の電算機では、VRAMにGraphicなんておくと、容量が足らないので、T-VRAMのみだったり、そもそもVRAMがなかったりなんかします(^^;)

で、Text Sideなのが、T-VRAM(Text Video RAM)、Graphic SideなのがG-VRAM(Grapich Video RAM)というわけなんです。


さてさて、でT-VRAMなんですけども、VAや98では大きく分けて、以下の構造になっています。

の2つですね(VAでは、I/O Mapped Memory領域、Sprite座標系、Sprite Data領域の3つが上記以外にもあるんですけどね)。

で、このT-VRAMがどこにあるのか・・・なんですけども、Memory上に存在しています(X1はI/O Portにぶらさがってるという噂を聞いたことがありますけど、見たことないのでわかんないです(^^;)。


VAの場合ですと、AddressはA000:0000 - A000:FFFF(VA2/VA3ではD000:FFFF)までとってあります。

A000:0000 - A000:1FFFまでが文字コード用、A000:8000 - A000:9FFFまでがアトリビュート用となっています。


また、98の場合ですと、AddressはA000:0000 - A000:7FFFまでとってあります。

A000:0000 - A000:3FFFまでが文字コード用、A000:4000 - A000:7FFFまでがアトリビュート用となっています。


機種毎に異なるのは、当然Machineの特性の違いによるものなんですけどね。


本当は、もっと詳しい説明もあるんですけども、あくまで「まめ知識」ですので、ここいらにしときます。

(詳細は別途資料をば、自分で準備してくださいな(^^;)


まぁ、これだけでは芸がないので、次は少し違う例を取り上げましょう。


;Sample Program 4

        Ideal
        P186
        Model   Small
        Stack   0200h

CodeSeg

        push   ds es

        mov    ax,cs
        mov    ds,ax
        mov    ax,0a000h
        mov    es,ax
        mov    si,Offset WordDatas
        mov    di,00300h

        mov    cx,00005
        cld
        rep    movsw 

        pop    es ds
        mov    ax,04c00h
        int    021h

WordDatas:
        db     'T',000h
        db     'e',000h
        db     's',000h
        db     't',000h
        db     '!',000h

        End


どうですか、画面の右上の方に「Test!」という文字が表示されたはずです。

つまり、ここでは、自由な位置に自由な文字数だけ表示できるようにするための骨子だけを実行したことになるんです。

ちなみに、転送文字がCodeのみでなく、Null Codeが含まれているのは、T-VRAMの設計上こうしなければならないだけです。

(全角Codeが2Bytesであるため、それに対応するためにこのような設計となっているんです(WordDatas項目の内容を五文字以内の全角文字に置き換えてみるとよくわかります)。


さらに、これを汎用的なものとする為に、以下のプログラムをくんでみましょう。

但し、アトリビュートは考慮していませんのであしからず(^^。


;Sample Program5

        Ideal
        P186
        Model  Small
        Stack  00200h

CodeSeg
        mov     ax,cs
        mov     ds,ax
        mov     si,Offset WordsData
        mov     ax,20
        mov     cx,[Word cs:WordsNumber]
        mov     dx,10
        call    WordsPrint

        mov     ax,04c00h
        int     021h

;呼び出す時;
;    AX:横軸
;    CX:文字数(2バイトで1文字とする)
;    DX:縦軸
;    SI:表示する文字の保管されているセグメントアドレス
;    DS:同じくオフセットアドレス
;かえる結果
;    None

        Proc    WordsPrint      Near

        pushf
        push    ax cx dx si di ds es

                shl     ax,1
                mov     di,ax
                shl     dx,5
                add     di,dx
                shl     dx,2
                add     di,dx
                mov     ax,0a000h
                mov     es,ax

                cld
                rep     movsw

        pop     es ds di si dx cx ax
        popf
        ret

        EndP

WordsNumber:
        dw      4

WordsData:
        db      'T',000h
        db      'E',000h
        db      'S',000h
        db      'T',000h

        End


少しだけ長めですけども、MainRoutineのAXが横軸位置、DXが縦軸位置、CXが文字数、DS:SIが文字列の保管されているアドレスとなっています。

それで、WordsPoint Procedureを呼び出せば、殆ど画面の自由な位置に自由な文字数だけ表示できるようになります

(尚、このSampleでは半角文字のみです)。


という事で、今回の講義内容はここまでにします。

Graphicを用いる方法は、まだG-VRAMというものの説明をしていませんので、ちょっとここでは省かせていただきますね。

(それに、かなり膨大なものとなりますので(^^;)

まぁ、基本的には殆ど変わらないんですけども、一番の違いは「文字データをApplicationがGraphic Dataとして持たなければならない」ということですね。

(内部Fontを用いる方法もあるんでけすけども、それだけじゃぁ芸がないので(^^;;;)


さてさて、ではでは次回講義内容は、「カーソル移動」です。

(カーソルといっても、Promptで点滅しているカーソルのことではなくって、例えばメニュー選択とかのを指します)

なお、次回の内容は少々機種依存性が高くなると思います。


尚、PC-88VA上では、以下のProcedureを先にCallしなければ、正しく動作しないことがあります。


;For PC-88VA/VA2/VA3 Procedure

        Proc    VRAMChnageToTVRAM       Near

        push    ax dx

                mov     dx,00153h
                mov     al,041h
                out     dx,al

        pop     dx ax
        ret

        EndP


Back


手元に実機も実行環境もありませんのでサポート不可です。

文章は執筆当時のものをそのまま掲載していますので、時代・時節と合わない表現が含まれています。

また、一部に半角カナ文字が使用されています。