やりたいことは、アセンブラが設定した配列をC++(またはC)の構造体に入れるってそれだけなんだけど、何故かはまっている。
アセンブラは適当なアドレスに値を入れる。こんな感じで。
0x00002840: 0x00000000 0x0000000 0x0009fc00 0x00000000 0x00002850: 0x00000001 ...これが配列の一要素。
っで、まぁこれはE820hで取得したメモリーマップなので、普通にこんな構造体で受け取る。
struct MemoryMapEntry { uint32_t baseAddrLow; uint32_t baseAddrHigh; uint32_t lengthLow; uint32_t lengthHigh; uint32_t type; }; // どこかの関数で MemoryMapEntry mapEntries = getMemoryMapEntry(); // これはアセンブラ内で定義した。これで普通ならいけるはずなんだけど、取り出される値がおかしい。上記のアドレスなら、
baseAddrLow = 0x00000000 baseAddrHigh = 0x00000000 lengthLow = 0x0009fc00 lengthHigh = 0x00000000 type = 0x00000001になるはずなんだけど、こんな感じに実際にはずれる。
baseAddrLow = 0x00000000 baseAddrHigh = 0x00000000 lengthLow = 0x00000000 lengthHigh = 0x00000000 type = 0x0009fc00感じとしては、20バイト取得できてないといけないのだが、12バイトしか取れてない感じ。なぜ?
これが普通の動作なのかなと思い、ちょっと実験してみた。
#includeこんなむちゃくちゃなコードでもなんか動いてるから不思議。struct sample { unsigned int val1; unsigned int val2; unsigned int val3; unsigned int val4; unsigned int val5; }; void* getsample() { static int *addr = (int*)0x404030; addr[0] = 0x00000000; addr[1] = 0x00000000; addr[2] = 0x00000000; addr[3] = 0x0009fc00; addr[4] = 0x00000001; return addr; } int main() { sample *s = (sample*)getsample(); printf("addr: %x\n", s); printf("%x, %x, %x, %x, %d\n", s[0].val1, s[0].val2, s[0].val3, s[0].val4, s[0].val5); return 0; }
っで、結果は普通に予定通りの値が取れていた。
コンパイラの最適化が効いてるからなのか(何もオプションつけてないけど)、別の要因で直にアドレスから取るのとは違うのかよく分からん。
何より腹が立つのは、以前はまともに動いていたのだ!ページングの実装を終えたらおかしくなった・・・
関係があるのかな、やっぱり・・・
2010/01/17 追記
原因が分かった。結論: まともに動いていました。
原因: VGAクラスで実装していたprintfメソッドの不具合。
64ビットの数値には%xの書式指定子が対応しておりません・・・
参考にしている人はいないと思うが、
64ビットの整数値を表示したいのに、可変引数のポインタを進める際に(int*)のポインタでやっとりました。つまり、8バイト移動させないといけないところを、4バイトしか進めていなかったっと。
これで2時間悩んだ。printfデバッグの限界やね。と勝手に納得・・・
No comments:
Post a Comment