Win16はWin32と違い,低レベルへのアクセスを許しています.そのため,ハードウェアを制御したい場合や低レベルにアクセスしたい場合,Win16を使うのが手っ取り早いと言えます. 確かに,ドライバなどを開発しWin32上から制御しないと,ほかのアプリケーションとともに動かした場合に不具合を生じることがあります.しかし,少し試したい場合などにWin16を使うと手間を省ぶくことができます. <表1-1> プログラムファイル
プログラムは,WinMainしかありません. <図1-1> プログラムの構造
WindowsをVGAモードなどで使っていると,A0000H(セグメントアドレスA000H,オフセットアドレス0000H)からビデオ用のRAMが割り当てられています.このエリアに直接書き込みを行います. ● 変数の宣言 unsigned int loop ; WORD FAR * lpScreen ; WORD selector ; 上記は,何の変哲もない変数の宣言です. ● アドレスの代入
selector = (WORD)&_A000h ; さあ,上の行は何をやっているのでしょう?単純に_A000hのアドレスをselectorという変数に代入しているだけです.ところで_A000hってどこにありましたっけ!そうそう,先頭のほうに以下のような宣言がありましたね. extern BYTE NEAR CDECL _A000h ; そうです._A000hは外部にあります.しかし,このプログラムは本体以外に外部モジュールはありません.では_A000hっていったいどこにあるのでしょう.ここで,_A000hの話は中断して次に進みます. lpScreen = (WORD FAR *)MAKELP( selector, 0 ); MAKELPマクロは,セグメントセレクタとアドレスオフセットを組み合わせて,メモリアドレスを指すlong(32ビット)ポインタを作成します.i386などのプロテクトモードでは,セグメントはセグメントアドレスではなくセレクタで表されます(注1-1). このMKELPマクロはWin16専用です.つまり,Windowsアプリケーションであっても,ある物理メモリのセレクタさえわかっていれば,物理メモリへアクセスすることができます.本格的なOSであれば,メモリ保護例外などが発生してしまいます.しかし,Windows 9xやWindows 3.1ではこのようなことができます. ● ビデオRAMへの書き込み for( loop = 0 ; loop < 0xFFF0 ; loop++ ) lpScreen[loop] ^= 0xFFFF ; ここでは,直接ディスプレイ領域のメモリ(VRAM)と0xFFFFでXORを取っています.このコードによって,表示画面が反転します.このように,GDIを使うことなく画面をアクセスすることができます. 注:1-1 セレクタやディスクプリンタについては,i386アーキテクチャの解説書を参照してください. 注:1-2 Win32ではこのプログラムをビルドすることはできません. Copyright 2000 北山 洋幸 |
|
Copyright 1997-2001 CQ Publishing Co.,Ltd.