30日でできるOS自作入門【16日目】
概要
これはMozyの1人アドベントカレンダー 2018 の16日目の記事です。
書こうとした経緯は、こちら
今日の内容
- ポインタに挑戦
今日やったこと
- 機能書いたプログラムをポインタを使って書き直す
bootpack.c
void io_hlt(void); void HariMain(void) { int i; /* iは32ビットの整数 */ char *p; /* pという変数は、BYTE [...]用の番地 */ for (i = 0xa0000; i <= 0xaffff; i++) { p = i; /* 番地を代入 */ *p = i & 0x0f; /* これで write_mem8(i, i & 0x0f); の代わりになる */ } for (;;) { io_hlt(); } }
ただし、warningが出ているな。
bootpack.c: In function `HariMain': bootpack.c:10: warning: assignment makes pointer from integer without a cast
なるほど。キャストが足りないのね。
p = (char *) i;
てな感じにして解決!
ハマりポイント
久々にポインタの概念が出てきたので、一応、少しググって思い出していた。
こうやって急に問われた時に正確な概念が返せないといけないねぇ。
p = (char *) i;
と
*p = i & 0x0f
の違いを説明してみよう。
これらのpをECXだとして、アセンブラぽくしてみると
MOV ECX, i
MOV BYTE [ECX], (i & 0x0f)
てな感じになるよね
こうすると違いがすごく明確で、ECXっていう「レジスタ」への書き込みなのか
それとも、ECX番地の「メモリ」への代入なのかとなる。
そもそも書き込む素子ですら違うのでめっちゃ明確に違うものとわかる。
これがC言語だと p なのか *p なのかの一文字で変わってしまうのよね。
知ったこと
そう言えば、char、short、intがそれぞれ1、2、4バイトの変数って知っていたけれども、AL、AX、EAXと対応する感じなんだなぁ。
こうやって既存のCを知っている状態でもっと低レベルを知ると納得できる部分がどんどん出てきていいですねぇ。