2

アセンブリ(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」が表示されました。

4

2 に答える 2

4

PC (または ACPI をサポートする他のマシン) で ACPI テーブルを読み取る必要があります。

これは合計サイズを 1 つの数値として与えるのではなく、メモリの各領域のメモリ サイズを与えることに注意してください。単純なマシンでは、2 つまたは 3 つの領域である可能性があります ( 0xA0000-0xFFFFF および BIOS が「PCI ホール」を置くことを決定した場所)。

ACPI リーダーを 1 つのセクターに収めるのは簡単なことではないと思いますが、ブート セクターの一部には約 400 バイトしか使用できないスペースがあることを考えると (ただし、パーティション テーブルを完全にスキップすると、ほぼすべてのセクターを使用できると思います)。 512バイトのうち)。

「C/C++ の呼び出し方法」に関しては、意味のある C または C++ プログラムを数セクター未満に収めることはできません。OS ブートローダーを調べて、コンパイラのセットアップをどのように達成するかを確認する必要があります (多くの場合、メモリにロードするのに適した特定の場所にあるコードを生成するための特別なツールも必要です)。直接実行されます)。このページはそのために役立つかもしれません(私はすべてを読んでいません。メモリの量さえわかるかもしれません):http://www.codeproject.com/Articles/36907/How-to-develop-your -own-boot-loader

于 2013-06-27T09:33:01.383 に答える
1

編集:私の間違い、ウィキは正しいですが、これをここに残しておくだけです...

wiki にタイプミスがあるようです - 次の行:

mov edx,0x0534D4150

次のようになります。

mov edx,0x050414D53

バイトが逆順になっていることに注意してください (x86 はリトル エンディアンであるため)。

于 2013-06-28T13:53:46.427 に答える