アセンブリ(NASM)で簡単なプログラムを書いています。ブート セクタがロードされると、コンピュータにインストールされているすべてのメモリ (RAM) をメガバイト単位で表示する必要があります。ブート セクタが読み込まれると、オペレーティング システム (DOS、Windows、Linux) が存在しないため、RAM の合計サイズを確認するにはどうすればよいでしょうか。私のコンピュータには 2 GB の RAM があります。私はインターネットでたくさん検索しましたが、解決策を見つけることができませんでした。
メモリ サイズが 2 GB であることを示す BIOS の割り込みはありますか? 古いコンピューターでメモリを表示するために使用されていた割り込みがありますが、2 GB すべてが表示されるわけではありません。確認しましたが、Ralph Brown List にこれに対する解決策はありません。誰かがBIOSについてもっと知っているかもしれません。BIOS がこの機能を提供しない場合、C/C++ を使用して合計 RAM サイズを確認できますか? アセンブリから C/C++ コードを呼び出しますか? 合計 RAM サイズを見つけるために使用される C/C++ の関数はどれですか?
アセンブリ コードはコールド ブートを実行するため、コードに機能を提供するオペレーティング システムが存在しないことに注意してください。
編集:
ウェブサイトhttp://wiki.osdev.org/Detecting_Memory_%28x86%29を読みました。int 15 が機能するかどうかを確認することにしました。そこで、この Web サイトからコードを取得し、編集して int 15 EAX = E820 が機能するかどうかをテストしました。しかし、それは機能せず、出力は .failed1 の「F」です。「F」は「サポートされていない機能」をチェックするために作成したテストケースです。テストケースは「F」、「G」、「H」です。これがコードです。
; use the INT 0x15, eax= 0xE820 BIOS function to get a memory map
; inputs: es:di -> destination buffer for 24 byte entries
; outputs: bp = entry count, trashes all registers except esi
do_e820:
xor ebx, ebx ; ebx must be 0 to start
xor bp, bp ; keep an entry count in bp
mov edx, 0x0534D4150 ; Place "SMAP" into edx
mov eax, 0xe820
mov [es:di + 20], dword 1 ; force a valid ACPI 3.X entry
mov ecx, 24 ; ask for 24 bytes
int 0x15
jc short .failed1 ; carry set on first call means "unsupported function"
mov edx, 0x0534D4150 ; Some BIOSes apparently trash this register?
cmp eax, edx ; on success, eax must have been reset to "SMAP"
jne short .failed2
test ebx, ebx ; ebx = 0 implies list is only 1 entry long (worthless)
je short .failed3
jmp short .jmpin
.e820lp:
mov eax, 0xe820 ; eax, ecx get trashed on every int 0x15 call
mov [es:di + 20], dword 1 ; force a valid ACPI 3.X entry
mov ecx, 24 ; ask for 24 bytes again
int 0x15
jc short .e820f ; carry set means "end of list already reached"
mov edx, 0x0534D4150 ; repair potentially trashed register
.jmpin:
jcxz .skipent ; skip any 0 length entries
cmp cl, 20 ; got a 24 byte ACPI 3.X response?
jbe short .notext
test byte [es:di + 20], 1 ; if so: is the "ignore this data" bit clear?
je short .skipent
.notext:
mov ecx, [es:di + 8] ; get lower dword of memory region length
or ecx, [es:di + 12] ; "or" it with upper dword to test for zero
jz .skipent ; if length qword is 0, skip entry
inc bp ; got a good entry: ++count, move to next storage spot
add di, 24
.skipent:
test ebx, ebx ; if ebx resets to 0, list is complete
jne short .e820lp
.e820f:
mov [mmap_ent], bp ; store the entry count
clc ; there is "jc" on end of list to this point, so the carry must be cleared
mov ah, 0x0E ; Teletype command
mov bh, 0x00 ; Page number
mov bl, 0x07 ; Attributes (7 == white foreground, black background)
mov al, mmap_ent ; Character to print
int 0x10
ret
.failed1:
push eax
push ebx
mov ah, 0x0E ; Teletype command
mov bh, 0x00 ; Page number
mov bl, 0x07 ; Attributes (7 == white foreground, black background)
mov al, 70 ; Character 'F' to print
int 0x10
pop ebx
pop eax
stc ; "function unsupported" error exit
ret
.failed2:
push eax
push ebx
mov ah, 0x0E ; Teletype command
mov bh, 0x00 ; Page number
mov bl, 0x07 ; Attributes (7 == white foreground, black background)
mov al, 71 ; Character 'G' to print
int 0x10
pop ebx
pop eax
stc ; "function unsupported" error exit
ret
.failed3:
push eax
push ebx
mov ah, 0x0E ; Teletype command
mov bh, 0x00 ; Page number
mov bl, 0x07 ; Attributes (7 == white foreground, black background)
mov al, 72 ; Character 'H' to print
int 0x10
pop ebx
pop eax
stc ; "function unsupported" error exit
ret
mmap_ent db 0
failmsg db 0
failmem db 'Failed', 0
;times 512-($-$$) db 0
;dw 0xAA55
編集:
nasm memext.asm -o memext.com -l memext.lst を使用しました。MagicISO を使用してブータブル イメージ ファイル memext.iso を作成し、Windows ディスク バーナーを使用して DVD/RW に書き込みました。Oracle VM をロードし、256 Mb の RAM、CD/DVD、2 GB のハードディスクを備えた新しい仮想マシンを作成しました。コールド ブート テスト用に DVD で起動しましたが、何も印刷されません。
また、コマンド コンソールを開いて memext と入力すると、出力として「F」が表示されました。