現代の量子力学

主に精進の様子を記録する日記帳です

4日目 C言語と画面表示の練習

1. C言語からメモリに書き込みたい
    画面に何か書き込むにはVRAMに何か書き込めばいい。とりあえずアセンブリ言語で書いてみる。
    C言語でwrite_mem8が使われると、アセンブリ言語で書いた_write_mem8に飛ばされて、引数はESP(スタックポインタ)に渡されるっぽい。
    C言語と連携する場合は自由に使っていいレジスタが決まっており、EAX、ECX、EDXの三つのみ。
INSTRSET命令
    [INSTRSET “i486p”] が追加されている。これはこのプログラムは486(CPUの世代)用のプログラムですよ〜と教えている。そうしないと、EAXがレジスタだと思われないらしい。
    ただ、NASMでこれを書くとエラーが出るので書かない。
C言語側の変更
    for文を使っている。
    VRAMはそれぞれの番地が画面上の画素に対応しているのでVRAMの番地に値を書き込むと画面表示が変えられる。
    VRAMの番地は0xa0000〜0xaffffで今回はfor loop で全部に白色に対応する値を書き込んでいるので真っ白画面になる。
    できた、目に見えてわかると良いですね。
 
2. しましま模様
    書き込む値を周期的に変えていく。&演算を使う。
    しましま模様が完成。
3. ポインタに挑戦
C言語でメモリに直接書き込む
    アセンブラで関数なんて作らなくても、C言語から直接メモリに書き込めばいいじゃない。
    char *p; でpがメモリ番地専用変数(ポインタ)であると宣言。charは1バイト。
    p = (char *) i ; でpに番地i を入れてあげて、
    *p = i & 0x0f; で番地p ( = i) に値を書き込む。
    ポインタやらアドレスやらCやC++で勉強したけど、低レイヤ側から学んだ方がしっくりくる。なんかちょっとわかった気がする。
 
ポインタについて
    MOV BYTE [i], (i, 0x0f) をどうにかしてC言語にやらせたい!
    つまり「メモリのi 番地に、i & 0x0f の計算結果を書き込みたい!」ということ。
    アセンブラとの対応関係は、
    p = (char *) i ; → MOV ECX, i
    *p = i & 0x0f ; → MOV BYTE [ECX], (i & 0x0f)
    上の代入式は、ECXという「レジスタ」への代入。下の代入式はECX番地の「メモリ」への代入、ということ。全然違うね。
    *p は BYTE [p] である
    
4. ポインタの応用(1)
    p にVRAMの先頭の番地(0xa0000)を入れておいて、*(p + i) = i & 0x0f; でもできる。
 
5. ポインタの応用(2)
    *(p + i) をp[i] とも書ける。配列。
 
6. 色番号設定
    今使っている8ビットカラーモードは色番号が0〜255しか使えない。
    が、この256色をプログラマが勝手に選ぶことができる。色番号16に#ffffff(RGB指定)を割り当てる〜みたいな感じ。この仕組みをパレットという。
static はDB命令?
    ちょっとまだ理解できてません…
関数io_out8
    装置番号で指定された装置にデータを送りつける関数。装置とはキーボードとか、マウスとか
    C言語ではこのOUT命令が無いのでアセンブラで作成。。
 
7. 四角形を書く
    画面左上を(0, 0)、右下を(319, 199)とすれば、画素座標(x, y)に対応するVRAMの番地は、
    0xa0000 + x + y * 320になる。
 
8. 今日の仕上げ
    すげ〜なんかそれっぽい