我ながら意味不明なタイトルだ。
やりたいことは、アセンブラが設定した配列を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デバッグの限界やね。と勝手に納得・・・