最初のBIOS命令が0xFFFFFFF0(RAMの「トップ」)にあるのはなぜですか?


51

BIOSは0xFFFFFFF0から最初の命令をロードすることを知っていますが、なぜこの特定のアドレスですか?たくさんの質問がありますが、少なくともそれらのいくつかで私を助けてくれることを願っています。

私の質問:

  • 最初のBIOS命令が4 GB RAMの「上部」にあるのはなぜですか?
  • コンピューターのRAMが1 GBのみの場合はどうなりますか?
  • 4 GBを超えるRAM(8 GB、16 GBなど)を搭載したシステムについてはどうですか?
  • スタックが何らかの値(この場合、0xFFFFFFF0にある値)で初期化されるのはなぜですか?

私は今日の午後、それについて読んだことがありますが、まだ分かりません。


28
質問ごとに1つの質問をお願いします。
ライトネスレースとモニカ

4
私は、受け入れられた答えがセグメント化されたメモリやアドレス指定モードについてまったく言及していないことを気に入っており、A20ラインが触れられている唯一の場所はコメントです。
imallett

Atmel AVRはアドレス0から実行を開始し、Freescale HCS08は0xFFFE、iircから開始します。各プロセッサフ​​ァミリには独自の特性があります。
ニックT

2
@imallett投稿者に詳細情報で回答を更新するよう求めるのではなく、ここで文句を言うことを決めるのが好きです。また、質問をする目的が現在完全に理解できるものについての知識を得ることであるにもかかわらず、OPがこの知識を見つけることができるとあなたが考える方法が好きです。
MonkeyZeus

2
これまでの@MonkeyZeusでは、他の9人のコメント担当者が既にそれを行っており、まだ変更されていません。私のコメントは皮肉ですが、空虚ではありませんでした。これは、将来のネチズンとOPに対する警告です。
imallett

回答:


57

0xFFFFFFF0x86互換CPUは、電源がオンになると命令の実行を開始します。これは、CPUのハードワイヤードで変更不可能な(追加のハードウェアなしで)側面であり、異なるタイプのCPUは異なる動作をします。

最初のBIOS命令が4 GB RAMの「上部」にあるのはなぜですか?

4 GBのアドレススペースの「最上部」にあり、電源投入時にBIOSまたはUEFI ROMがこれらのアドレスの読み取りに応答するように設定されています。

これがなぜであるかについての私の理論:

プログラミングのほとんどすべてが、連続したアドレスでより良く機能します。CPU設計者は、システムビルダーがCPUで何をしたいのかわからないため、CPUがさまざまな目的でスペースの真ん中にアドレススマックを必要とするのは悪い考えです。アドレス空間の最上部または最下部に「邪魔にならないようにする」ことをお勧めします。もちろん、この決定は、8086がMMUを持たない新しいときに行われたものであることを忘れないでください。

8086では、メモリ位置0以上に割り込みベクトルが存在していました。割り込みベクトルは既知のアドレスにある必要があり、柔軟性のためにRAMに配置することが望まれていましたが、CPU設計者はシステムにどのくらいのRAMが配置されるかを知ることができませんでした。したがって、0から始めてそれらを処理するのは理にかなっています(1978年に8086が発明されたシステムには4ギガバイトのRAMがないため、RAMが0xFFFFFFF0であると期待するのは良い考えではありませんでした)。上限で。

もちろん、少なくとも80286以降では、割り込みベクトルは0以外の別の開始位置に移動できますが、最新の64ビットx86 CPUは8086モードで起動するため、互換性のためにすべてが古い方法で動作します(とんでもないように) DOSを実行できるようにx86 CPUを引き続き必要とするのは2015年のことです)。

したがって、割り込みベクトルは0から開始して上方向に動作するため、ROMは上から開始して下方向に動作しなければなりません。

コンピューターのRAMが1 GBしかない場合はどうなりますか?

32ビットCPUには、4,294,967,296個のアドレスがあり、0(0x00000000)から4294967295(0xFFFFFFFF)までの番号が付けられています。ROMは一部のアドレスで使用でき、RAMは他のアドレスで使用できます。CPUのMMUを使用すると、オンザフライで切り替えることもできます。RAMはすべてのアドレスに存在する必要はありません。

RAMが1 GBのみの場合、一部のアドレスは読み取りまたは書き込み時に何も応答しません。これにより、そのようなアドレスにアクセスしたとき、またはシステムがロックアップしたときに、無効なデータが読み取られる可能性があります。

4 GBを超えるRAM(8 GB、16 GBなど)を搭載したシステムはどうですか?

多少シンプルに保つ:64ビットCPUには、たとえば、より多くのアドレス(64ビットにするものの1つです。たとえば、0x0000000000000000から0xFFFFFFFFFFFFFFFF)があるため、余分なRAMは「適合」します。CPUがロングモードにあると仮定します。それまではRAMがあり、アドレス指定できません。

スタックが何らかの値(この場合、0xFFFFFFF0にある値)で初期化されるのはなぜですか?

電源投入時にx86がスタックポインターを割り当てるものについてはすぐには見つかりませんが、システム内のRAMの量がわかると、初期化ルーチンによって最終的に再割り当てする必要があります。(以下のコメントの@Eric Towersは、電源投入時にゼロに設定されると報告しています。)


7
アドレス空間は、物事をハードウェアによって割り当てることができる大きな空間と考えるのが最善です。CPUがメモリを読み書きするとき、実際にはバスを介して通信を実行し、ハードウェアはRAMやROMなどが特定のアドレス範囲で応答していることを確認できます。したがって、そのようなハードウェアは、CPUがリセットされたときにROMが0xFFFFFFF0で応答することを確認する必要があります。ROMがRAMの直後に表示されるという固有の義務はありません。このようなハードウェアの機能に応じて、ハードウェアが指示する場所にも表示されます。
ローレンス

4
ROM、RAM、またはその他によって使用されない「穴」または未割り当てのスペースが存在する可能性があります。通常、これらにアクセスするとシステムがロックアップします。
ローレンス

16
この回答は、CPUが16ビットモードのときに32アドレスビットを使用できることを前提としています。ただし、16ビットモードでは20アドレスビットしか使用できません。0xFFFFFFF0CPUが32ビットモードに切り替えられるまで、アドレスに到達できません。前回BIOSコードを詳しく調べたとき、エントリポイントはにありました0xFFFF0
カスペルド

6
@MichaelKjörling計算が間違っています。シフトされたセグメントとオフセットはORされず、追加されます。したがって、論理FFFF:FFF0は物理(1)0FFE0です(A20が有効な場合、先頭に1が存在します)。
ルスラン

9
@kasperdハックがあります-最初のロングジャンプが行われるまで、メモリマネージャーの上位12ビットが1に設定されます。そう、論理的には、あなたはで作業しています0xFFFF0が、実際には、にマップされ0xFFFFFFF0ます。私は、これは8086との互換性のために行われていた期待-それは、より現代のCPUは、両方の出現を使用し0xFFFF0ますが、32ビットCPU、実際にアクセス0xFFFFFFF0(BIOSのROMにマッピングされました)。
ルアーン

26

RAMの最上部にはありません。これは、イーサネットコントローラなどの拡張カード上のメモリとともに、アドレスがメモリアドレス空間の最上部にあるROMにあります。少なくとも4 GBがインストールされるまで、RAMと競合しないように、そこにあります。4 GB以上のRAMを搭載したシステムは、競合を解決するために2つのことを実行できます。安価なマザーボードは、ROMの場所と競合するRAMの部分を単に無視します。まともなものは、そのRAMを再割り当てして、4 GBマークより上のアドレスを持つように見せます。

あなたがスタックについて何を尋ねているのか分かりません。もちろん、ROMに初期化されていません。CPUがリセットされると、最初は「リアルモード」になり、元の8086と同様に動作し、16ビットのセグメント化されたアドレス指定を使用して、1 MBのメモリのみにアクセスできます。BIOSコードはその1 MBの上部にあります。BIOSは、RAMのどこかを選択してスタックをセットアップし、最初のブート可能ドライブの最初のセクターをロードして実行します。32ビットモードまたは64ビットモードに切り替えて、独自のスタック(タスク/スレッドごとに1つ)をセットアップしたら、OSに任されます。


1
回答ありがとうございましたが、@ LawrenceCが彼の回答の詳細を教えてくれ、全体がどのように機能するかを助けてくれました。とにかくありがとうございました!私はあなたに賛成票を差し上げます:3
フェルナンドパラディーニ

13

まず、これは実際にはRAMとは関係ありません。ここではアドレス空間について説明しています -メモリが16 MiBしかない場合でも、32ビットCPUには32ビットのアドレス空間がすべて残っています。

これは、あなたの最初の質問にすでに答えています。これが設計された時点では、実世界のPCには4 GiBのメモリに近いものはありませんでした。それらは、1〜16 MiBの範囲のメモリでした。アドレス空間は、すべての意図と目的のために、無料でした。

さて、なぜ0xFFFFFFF0なのか?CPUはBIOSの量を知りません。BIOSによっては数キロバイトしか使用できないものもあれば、メガバイト単位のメモリを使用するものもあります。また、さまざまなオプションのRAMを使用することすらありません。CPUは、起動するために何らかのアドレスに配線する必要があります-CPUを構成する必要はありません。しかし、これはアドレス空間のマッピングにすぎません-アドレスはBIOS ROMチップに直接マッピングされます(はい、これは、その数がある場合、この時点で完全な4 GiBのRAMにアクセスできないことを意味します-それは特別なことではなく、多くのデバイスはアドレス空間に独自の範囲を必要とします)。32ビットCPUでは、このアドレスは完全な16バイトを提供して、非常に基本的な初期化を行います。これは、セグメントをセットアップし、必要に応じてアドレスモードを設定するのに十分です(実際のブート「手順」。この時点では、RAMをまったく使用していません-それはすべてマップされたROMです。実際、RAMはこの時点で使用する準備ができていません-それはBIOS POSTの仕事の1つです!さて、あなたは考えているかもしれません-16ビットのリアルモードはどのようにアドレス0xFFFFFFF0にアクセスしますか?確かに、セグメントがあるので、20ビットのアドレス空間がありますが、それでもまだ十分ではありません。トリックがあります-最初のロングジャンプを実行するまでアドレスの上位12ビットが設定され、上位アドレススペースへのアクセスが許可されます(0xFFF00000より低いものへのアクセスは拒否します-ロングジャンプを実行するまで) 。

これはすべて、最新のオペレーティングシステムのプログラマー(ユーザーはもちろん)からほとんど隠されているものです。通常、あなたはそれほど低レベルのものにはアクセスできません-いくつかのものはすでにサルベージを超えています(CPUモードを自由に切り替えることはできません)、いくつかはOSカーネルによって排他的に処理されます。

したがって、MS DOSでの旧式のコーディングからより良い見方が得られます。デバイスメモリがアドレス空間に直接マップされる別の典型的な例は、ビデオメモリへの直接アクセスです。たとえば、ディスプレイに高速でテキストを書き込みたい場合は、アドレスに直接書き込みましたB800:0000(さらにオフセット-80x25テキストモードでは、これは(y * 80 + x) * 2私のメモリが適切に機能する場合-文字ごとに2バイト、行ごとに意味します)。ピクセルごとに描画する場合は、グラフィックモードと開始アドレスA000:0000(通常、ピクセルあたり8ビットで320x200)を使用しました。高性能なものを実行することは、通常、デバイスマニュアルに飛び込んで、それらに直接アクセスする方法を見つけ出すことを意味しました。

これは今日まで残っています-それはただ隠されています。Windowsでは、デバイスマネージャーでデバイスにマップされたメモリアドレスを確認できます-ネットワークカードなどのプロパティを開き、[リソース]タブに移動します-すべてのメモリ範囲項目は、デバイスメモリからメインアドレススペースにマッピングされます。そして、32ビットでは、これらのデバイスのほとんどが2 GiB(後の3 GiB)マークの上にマッピングされていることがわかります-これもユーザーが使用可能なメモリとの競合を最小限に抑えるためですが、これは実際には仮想メモリの問題ではありません(アプリケーションは、実際のハードウェアアドレス空間に近づきません。たとえば、独自の仮想化されたメモリチャンクがあり、RAM、ROM、デバイス、またはページファイルなどにマッピングされます。

スタックについては、デフォルトでは、スタックが上から成長することを理解するのに役立つはずです。したがってpush、新しいスタックポインタはにある場合、0xFFFFFECつまり、BIOS initアドレスへの書き込みを試みていません:)もちろん、BIOS initルーチンは、再マップする前にスタックを安全に使用できることを意味します。どこかより便利です。古い学校のプログラミングでは、ページングが事実上のデフォルトになる前に、スタックは通常RAMの終わりで始まり、アプリケーションメモリの上書きを開始すると「スタックオーバーフロー」が発生しました。メモリ保護により多くの変更が行われましたが、一般に、可能な限り後方互換性が維持されます。最新のx86-64 CPU でもMS DOS 5を起動できることに注意してください -または、Windowsがページングについてまったくわからない多くのDOSアプリケーションを実行する方法。


3
優れた答えは、単に拡張して、最新のプロセッサがA20ラインマスキングのようなハッキングを落とし始めていると言うことです。そのため、古いエッジケースのサポートはなくなりつつあります。
基本的な

2
最後の段落まで:BIOSはスタックを「自由に」使用することはできません。ROMに書き込むことはできません(ROM 0xFFFFFFECにマップされます)。これは、noだけでなくpush、たとえばno callも意味します。これらは、RAMの準備ができるまで待つ必要があります。
ヴィー

7

記載されている他のポイントに加えて、住所何であるかを理解することが役立つ場合があります。新しいアーキテクチャは事態を複雑にしますが、歴史的には、マシンは各メモリサイクルで20から32ワイヤで目的のアドレスを出力します(アーキテクチャによって異なりますが、ペアが必要なのか、4バイトが同時に必要なのかを注意する特殊なトリックがあります); メモリシステムのさまざまな部分は、これらのワイヤの状態を調べ、高い値と低い値の特定の組み合わせを見つけたときにアクティブになります。

32のアドレスワイヤを備えたマシンが1 MBのRAMと64 KBのROMを使用するだけでよい場合(一部の組み込みコントローラでもっともらしい)、最上位のアドレスワイヤが低いすべてのアドレスのRAMと、それがあったすべてのアドレスのROM高い。次に、下位20のアドレスワイヤをRAMに結び付けて1,048,576バイトの1つを選択し、下位16のアドレスワイヤもROMに配線して65,536バイトの1つを選択します。残りの11本のアドレスワイヤは、何にも接続されません。

このようなマシンでは、アドレス0x00100000-0x001FFFFFへのアクセスは、RAMアドレス0x00000000-0x000FFFFFへのアクセスと同等です。同様に、アドレス0x000200000-0x0002FFFFF、または0x7FF00000-0x7FFFFFFFF。0x80000000を超えるアドレスはすべてROMを読み取り、スペース全体で64Kパターンが繰り返されます。

プロセッサには4,294,967,296バイトのアドレス空間がありますが、ハードウェアに多くの異なるアドレスを認識させる必要はありません。リセットベクターをアドレス空間の上部近くに配置することは、システムに搭載されているRAMとROMの量に関係なくうまく機能する設計であり、アドレス空間を完全にデコードする必要がありません。


良い点-アドレス指定可能な64ビットメモリ空間(またはその1x10 ^ -12)に近いものをサポートする64ビットハードウェアは見つかりません。
基本的な

3

私の理論は、負のロジックを使用しているため、デジタル1(1)はまったく張力がない(0ボルト)初期化時に最後の4ビットに張力をかけるだけで、プログラムカウンター(または命令ポインター)が1111 1111で停止します1111 1111 1111 1111 11110000。ほとんどの(古い)CPUは16ビットで、古いニブルは単一のアドレスチップでアドレス指定できるため、上位28ビットをアドレス指定する必要はありません。現在、32ビットと互換性のある64ビットと32ビットと16ビットの互換性があるため、ハードウェアの構成は改善されていますが、方法はそのままです。また、biosesは常に64ビットまたは32ビットがプログラムされているわけではありません。私の意見では、記憶は常に同じではないため、BIOSは同じ最初のセグメントに配置する必要があります。対処されたBIOSの表示方法は、常に実際のアドレスではありません。ただ私に教えられた...


2

リセット時に、8088/8086互換CPUは、0FFFF0で命令を実行します。これは、1メガバイトの制限より16バイト下です。通常、この場所(PC実装の場合)のROMはBIOSであるため、BIOS ROMの最後には、BIOS ROMの先頭へのジャンプがあります。

ここに示す:開始ベクトルとその背後にある「日付」署名、IBM 5150 PC 8KB eprom dump bios日付:10/19/1981

00001FEE  FF                db 0xff
00001FEF  FF                db 0xff
00001FF0  EA5BE000F0        jmp word 0xf000:0xe05b
00001FF5  3130              xor [bx+si],si
00001FF7  2F                das
00001FF8  3139              xor [bx+di],di

アドレス指定は8KB $ 2000 romであり、開始アドレス(絶対遠JMP、他の場所、この場合は8KB rom内にありますが、そのrom内の最下位アドレスではありません)を$ FFFFに配置します。 $ 0セグメント化または$ FFFF0リニア。

互換性に関しては、「将来」または現在のプロセッサがアドレスの前にもっと多くのFがあると「予想」する場合、それは問題ではありません。古いシステムでの新しいCPUの互換性のために、追加のアドレスラインは未接続のままであるため、データバス上のデータはまったく同じです。最下位ビットがFFFF0のままである限り。

(1MBのRAMとそのRAMの最後にROMが配置されているシステムでは、それ以外の場合は、上位アドレスと通信しているが、まったく同じデータを取得していることを喜んで「考え」ます。 A19より上の住所行)

世界は単なる「pcs」ではないことに注意してください... IBM PCは「事故」であり、これらのプロセッサーは「pcs」用に特別に設計されたものではなく、単なるpcs以外の多くのもの(サテライト、武器システムなど)。通常、32ビットと64ビットの保護モードは望ましくありません。(たとえば、仮想8086モードは、新しい(386+)バージョンを選択する理由としてはるかに興味深いです)。したがって、「後方互換性」には、「dosを実行する」だけでなく、もっと多くのことがあります。


1

マザーボードは、リセットベクタでの命令がBIOSエントリポイントにマップされたメモリ位置へのジャンプであることを保証します。このジャンプは、電源投入時に存在する非表示のベースアドレスを暗黙的にクリアします。これらのメモリロケーションはすべて、チップセットが保持するメモリマップのおかげで、CPUが必要とする正しい内容を持っています。これらはすべて、BIOSを含むフラッシュメモリにマップされます。これは、この時点でRAMモジュールにランダムながらくたがあるためです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.