1. ホーム
  2. assembly

[解決済み] x86アセンブリで160x100モードを実現する

2022-02-15 10:29:18

質問

IBM CGAでCRTCを使って行の高さを2ピクセルに変更することで、擬似的に160×100のグラフィックモードが実現できることは以前から知っていたのですが。数日前からこれを実現しようとしているのですが、行き詰まっています。

その インテル® オープンソース HD グラフィックスと インテル® Iris™ グラフィックス・プログラマーズ・リファレンス・マニュアル claim 45ページ(PDFでは59ページ)のMaximum Scanline Registerに書き込めばできる、あるいはそこから解釈しています。

メモリアドレス3B5に直接、00000001bという値、つまり2スキャンラインのコードで書き込んでみたのですが、どうでしょうか?これは、私がDOSBoxでそれをテストしたとき、全く何もしませんでした。

もしよろしければ、私が書いたNASMでアセンブルするコードを見てみてください。

BITS 16
xor bx,bx
mov ax, 3b5h
mov es, ax
mov ah, 00000001b
mov BYTE [es:bx], ah    ; write 00000001b to 0x03b5:0000, right?
cli
hlt

私はこのような低レベルのものにまだあまり自信がないので、何か手助けがあればありがたいです。

どのように解決するのですか?

3b5hではなく、3b50hのアドレスに書き込んでいるのですね。もし、3b5hを書き込みたいのであれば、ESに0をロードして、次のようにします。 mov BYTE [es:3b5h], 01 しかし、それはあなたがしたいことでもありません。リンク先のマニュアルにある3b5hというアドレスはquot;I/Oアドレスで、全く別のアドレス空間に存在し、アクセスするには専用のINとOUT命令を使う必要があるということです。

I/Oアドレス3b5hに値01を書き込むには、次のようなコードになります。

mov dx, 3b5h
mov al, 01
out dx, al

の唯一の形式であることに注意してください。 OUT命令 を使用することができます。DXレジスタでアドレスを指定し、ALレジスタでそのI/Oアドレスに書き込むデータを提供する必要があります。

ただし、これも正しくない。リンク先のマニュアルにあるように、I/Oアドレス3b5hはMDAデータポートで、CGAデータポートはI/Oアドレス3d5hにあります。最後に、I/Oアドレス3d5hからアクセスされるレジスタは、"Maximum Scanline Register"だけではありません。このアドレスを使用するレジスタは数種類あります。どのレジスタに書き込むかは、まず、I/Oアドレス3d4hのCGA CRT Controller Index Registerにインデックス値を書き込んで選択する必要があります。つまり、以下のようなコードになります。

mov dx, 3d4h   ; CGA CRTC Index Register
mov al, 09h    ; Maximum Scan Line Reigster
out dx, al
mov dx, 3d5h   ; CGA CRTC Data Port
mov al, 01     ; 2 scan lines
out dx, al

VGAは最大走査線レジスタに他のパラメータを追加するので、これはまだ正しくないかもしれないことに注意してください。これらの値を保持する必要があるかもしれませんが、実際のCGAハードウェアでは、レジスタが読み取り専用であるため、それは不可能です。実際のCGAビデオカードをエミュレートするコードの精度にもよりますが。