メモリマップを取得する [BIOS]
PC/AT互換機上で使用可能なメモリ容量を取得する方法は複数あるが、
そのうち4GB以上のメモリを認識できるBIOSファンクションはINT 15h : E820hのみ。
これを利用すると4GB以上の範囲を含むすべての範囲についてのメモリの割り当て状況(容量)を知ることができる。
※ただし1MB以下の領域(0~100000h)についてはIBM PCに由来する特殊な予約領域が存在するため正確でない。
BIOSコールフアンクション INT 15h, EAX = E820h : Query System Address Map
引数 : EBX=0 ECX=結果のレコードデータ長(20以上) EDX='SMAP' ES:DI=結果の出力先アドレス
返値 : EAX='SMAP'、EBX=0ならメモリマップ全て取得済み、EBX=0以外なら未取得のデータがある
取得したメモリマップのデータは次のような形式になっている。
基底アドレス(8バイト)|サイズ(8バイト)|タイプ(4バイト)|ACPI 3.0拡張属性情報(4バイト)
タイプ=1 の範囲が使用可能なメモリ領域で、1以外の範囲がシステム予約領域。
これはレコードデータ長を24バイトにした場合であって、それ以外ではどうなるのか未確認。
次はメモリマップを取得するプログラムの一部
;定数 ;MMBASE=メモリマップのデータ出力先アドレス ;MMSIZE=0x18 (メモリマップのレコードあたりサイズ(バイト)) mov edi,MMBASE mov ebx,0 ;ebxは最初だけ0指定 QUERY_MEMORY_MAP: mov eax,0xe820 mov ecx,MMSIZE mov edx,0x534d4150 ;edx='SMAP' int 0x15 ;BIOS割り込み jc FIN ;キャリーフラグが立ったら異常終了 add di,MMSIZE or ebx,ebx jnz QUERY_MEMORY_MAP;ebx=0なら繰り返しを抜ける FIN:
こちらにサンプルプログラムのソースコードを置いておきます。
NASMでアセンブルして利用してください。
→ https://radioc.web.fc2.com/
以下は3GBのRAMを搭載したPC/AT互換機での実行結果(Type=1の結果のみ抜粋。)
Base address(QWORD) |Length(QWORD) |Type(DWORD)|ACPI3(DWORD) 00 00 00 00 00 00 00 00 00 00 00 00 00 09 C8 00 00 00 00 01 87 BB A8 0F 00 00 00 00 00 10 00 00 00 00 00 00 B7 33 C0 00 00 00 00 01 28 24 44 B6 00 00 00 00 B7 5A 40 00 00 00 00 00 00 00 10 00 00 00 00 01 7C 8B 00 00 00 00 00 00 B7 61 F0 00 00 00 00 00 00 00 10 00 00 00 00 01 41 20 3A 52 00 00 00 00 B7 69 40 00 00 00 00 00 00 16 C0 00 00 00 00 01 00 00 00 00
Lengthの数字を全て足すと 3075762176Bytes ≒ 2933.28MB (2.86GB) が使用可能なメモリ容量であることが分かる。
逆にいえば約100MB分のメモリがOSやプログラムが使用できないシステム予約領域として割り当てられているということ。
(メモリ空間上、システム予約領域は実メモリの領域となるべく重ならないようになっているが、32ビット環境で約3GB以上のメモリを積んでいる場合は一部の実メモリがシステム予約領域と重複してしまうことがある。)
Windows 7のコントロールパネルの「システム」画面では実装メモリの欄が「2.87 GB 使用可能」となっていた。
これは上の結果の 2.86GB とほぼ一致する。