boot – なぜ最初の BIOS 命令が 0xFFFFFFF0 (RAM の先頭) にあるのか?

bios boot kernel memory

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

My questions:

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

今日の午後に読んだけど、まだ理解できない

  57  Fernando Paladini  2015-10-18


ベストアンサー

0xFFFFFFF0は、x86互換CPUが電源を入れると命令の実行を開始するところです。これはCPUのハードワイヤードされた(余計なハードウェアがない)変更不可能な側面であり、CPUの種類によって挙動が異なる

なぜ最初のBIOS命令が4GB RAMの “上 “にあるのか?

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

なぜそうなのかについての私の推理です

プログラミングでは、ほとんどすべてのものが連続したアドレスで動作するようになっています。CPU の設計者は、システムビルダが CPU で何をしたいのかを知らないので、CPU が様々な目的のためにアドレス空間の真ん中にあるアドレスを要求するのは良くありません。それは、アドレス空間の一番上か一番下に「邪魔にならないように」しておく方が良いのです。もちろん、この決定は、MMUを持っていなかった8086が新しいときに行われたことに留意してください

8086では、割込みベクタはメモリロケーション0以上に存在していました。割り込みベクタは既知のアドレスである必要があり、柔軟性のために RAM に存在することが望まれていましたが、CPU 設計者はシステムにどのくらいの RAM があるかを知ることはできませんでした。そのため、0から始めて上に向かって作業するのが理にかなっていました(8086が発明された1978年当時は4GバイトのRAMを持つシステムはなかったので、RAMが0xFFFFFFF0にあることを期待するのは良い考えではありません)が、ROMはその上限になければなりません

もちろん、少なくとも80286から始まって、割り込みベクタは0以外の別の開始位置に移動することができますが、現代の64ビットx86 CPUはまだ8086モードで起動するので、互換性のためにすべてのものはまだ古い方法で動作します(2015年になってもDOSを実行できるようにするためにx86 CPUを必要とするのは馬鹿げているように聞こえます)

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

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

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

RAMが1GBしかないため、一部のアドレスは読み書きされても何も反応しません。このため、そのようなアドレスにアクセスしたときに無効なデータが読み込まれたり、システムがロックアップしたりすることがあります

4GB以上のRAM(例:8GB、16GBなど)を搭載したシステムはどうですか?

これをやや単純にしておくと、例えば、64 ビット CPU はより多くのアドレスを持っています (これは 64 ビットにするものの 1 つであり、例えば、0x0000000000000000 から 0xFFFFFFFFFFFF など)。CPUがロングモードになっていると仮定します。それまではRAMは存在していますが、アドレス指定ができないだけです

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

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

60  LawrenceC  2015-10-19


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

スタックについて何を聞いているのかよくわかりません。それは確かにROMにあるように初期化されていません。CPUがリセットされると、最初は「リアルモード」で、オリジナルの8086と同じように動作し、16ビットのセグメント化されたアドレッシングを使用して、1MBのメモリにのみアクセスできるようになります。BIOSコードはその1MBの一番上にあります。BIOSはスタックをセットアップするためにRAMのどこかを選択し、最初のブート可能なドライブの最初のセクタをロードして実行します。一旦引き継ぎ、独自のスタック(タスク/スレッドごとに1つ)をセットアップした後、32または64ビットモードに切り替えるかどうかはOS次第です

28  psusi  2015-10-18


まず、これはRAMとは関係ありません。ここではアドレス空間の話をしているのですが、たとえメモリが16MiBしかなくても、32ビットCPUでは32ビットのアドレス空間をフルに利用することができます

これはあなたの最初の質問の答えになっています。これが設計された当時、現実世界のPCは4GiBの完全なメモリを持っていませんでした。アドレス空間は、どこから見ても自由でした

さて、なぜ正確には0xFFFFFFF0なのか?CPUはBIOSがどれだけあるかを知りません。BIOSの中には数キロバイトのメモリしか使わないものもあれば、フルメガバイトのメモリを使うものもあります。CPUは何かのアドレスにハードワイヤードして起動しなければならない – CPUを設定するためには何もありません。しかし、これはアドレス空間のマッピングに過ぎません – アドレスはBIOS ROMチップに直接マッピングされます(はい、これはあなたがそれだけの数を持っている場合は、この時点では4GiBのRAMのフルアクセスを取得しないことを意味します – しかし、それは特別なことではありません、多くのデバイスは、アドレス空間に独自の範囲を必要とします)。32 ビット CPU では、このアドレスで 16 バイトの基本的な初期化を行い、セグメントと必要に応じてアドレスモード (覚えておいてください、x86 は 16 ビットのリアルモードで起動します – アドレス空間はフラットではありません) を設定して、実際のブート「プロシージャ」にジャンプします。この時点では、RAM は全く使用していません。実際、この時点では RAM は使用する準備ができていません – これは BIOS POST の仕事の一つです。さて、あなたは考えるかもしれません – 16 ビットのリアルモードはどのように 0xFFFFFFF0 のアドレスにアクセスするのでしょうか?確かに、セグメントがあるので、20ビットのアドレス空間がありますが、それでも十分ではありません。アドレスの上位12ビットは、最初のロングジャンプを実行するまで設定されており、上位のアドレス空間へのアクセスが可能です

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

このように、MS DOS の昔ながらのコーディングからは、より良いビューが得られます。デバイスメモリがアドレス空間に直接マッピングされるもう一つの典型的な例は、ビデオメモリへの直接アクセスです。例えば、ディスプレイにテキストを速く書きたい場合、アドレス B800:0000 (プラスオフセット – 80×25 テキストモードでは、私の記憶が正しければ、これは (y * 80 + x) * 2 を意味します – 1 文字あたり 2 バイト、1 行ずつ) に直接書き込んだとします。ピクセル単位で描画したい場合は、グラフィックスモードと A000:0000 (通常、320×200、1ピクセルあたり8ビット) の開始アドレスを使用します。何か高性能なことをするには、通常、デバイスのマニュアルに直接アクセスする方法を見つけるために飛び込むことを意味していました

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

スタックに関しては、デフォルトではスタックは上から成長していくことを理解するのに役立つはずです。つまり、pushを実行した場合、新しいスタックポインタは0xFFFFFECになります – 言い換えれば、BIOSのinitアドレスに書き込もうとしていないということです :)これはもちろん、BIOS の init ルーチンがスタックをより有用な場所にリマップする前に、スタックを安全に使用できることを意味します。ページングが事実上のデフォルトになる前の旧式のプログラミングでは、スタックは通常 RAM の端から始まり、アプリケーションメモリを上書きし始めると「スタックオーバーフロー」が起こりました。メモリ保護はこの多くを変更しましたが、一般的には可能な限り後方互換性を維持しています – 最も近代的な x86-64 CPU であっても MS DOS 5 を起動することができます – あるいは、Windows はページングを知らない多くの DOS アプリケーションを今でも実行することができることに注意してください

17  Luaan  2015-10-19


前述の他の点に加えて、アドレスとは何かを理解するのに役立つかもしれません。新しいアーキテクチャは物事を複雑にしていますが、歴史的には、マシンは各メモリサイクルで20から32本のワイヤに所望のアドレスを出力していました(アーキテクチャに応じて、それが同時にバイトのペアまたは4組にする必要があるかどうかに注意するためのいくつかの特別なトリックを使用して)

32 個のアドレス線を持つマシンが 1MB の RAM と 64KB の ROM を使用するだけで済むとしたら [組み込みコントローラの場合は非常に考えやすい]、一番上のアドレス線が低いアドレスの場合は RAM を起動し、高いアドレスの場合は ROM を起動するかもしれません。一番下の20個のアドレス・ワイヤはRAMに接続されて1,048,576バイトの中から1つを選択し、一番下の16個のアドレス・ワイヤは65,536バイトの中から1つを選択します。残りの11本のアドレス線は、単に何も接続されていないことになります

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

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

9  supercat  2015-10-20


私の考えでは、負のロジックを使用しているため、デジタルの1は全くテンションがかかりません(Oボルト)。 初期化時に最後の4ビットにテンションをかけるだけなので、プログラムカウンタ(または命令ポインタ)は1111 1111 1111 1111 1111 1111 1111 1111 0000になります。昔のCPUは16ビットだったので、上位28ビットをアドレス指定する必要はありません。今は32ビットと32ビットの互換性を持つ64ビットがあり、32ビットと16ビットの互換性を持つ32ビットがあるので、ハードウェアは改善されたが、方法は変わらない。また、バイアスは常に64ビットまたは32ビットプログラムされていません。私の意見はまた、メモリが常に同じではないので、バイオスは同じ最初のセグメントに配置する必要があります。我々はアドレスのバイオスを参照してください方法は、すべての時間は、実際のアドレスではありません。ちょうど私の教え

3  Agguro  2015-10-22


通常、この位置にあるROMは(PCの実装では)BIOSになるので、BIOS ROMの最後にBIOS ROMの先頭へのジャンプがあります

ここに示されているのは、開始ベクトルとその背後にある「日付」署名、IBM 5150 PC 8KB eprom dump bios date: 10/19/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とROMがそのRAMの端に配置されていて、他には何もないシステムでは、それらの実装がA19よりも高いアドレスラインを聞いたことがないので、それはそれがより高いアドレスに話していると喜んで「考える」でしょうが、全く同じデータを取得します)

世界は「PC」だけではないことに注意してください… ibm の PC は「偶然」だったのです。32ビットと64ビットの保護されたモードは、通常、望まれていません。(例えば、仮想 8086 モードは、より新しい (386+) バージョンを選択する理由として、より多くの興味深いものです)

3  HRH Sven Olaf von CyberBunker  2017-05-03


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

1  viktorkh  2018-06-02


iAPx86 ファミリーは、ibm pc 以外の他のものの全体の多くに入った一般的なチップセットです (これはちょっとランダムに単にインテルのチップセットを購入することを決めた (インテルはそれが使用されるように意図した完全なセットではありませんが) とそれから pc を構築します

スタートアドレスを先頭に持っていると(スタートアドレスは常にROMでなければならない)、追加のアドレスラインをデコードする必要がなくなります(8088といくつかのバスデマルチプレックスロジック、512バイト(キロやメガではなくバイトです。)のROMを取り、$0000-$0200の間で接続してもスタートアドレスは$001F0のままです(先頭ビットはすべて’1’、最小有効ニブルはすべてゼロです)

(システムがどちらかの面で拡張可能であることを前提としている場合は、真ん中に隙間を残しておくことになります。)

i/o は独自の選択ピンと命令 (IN/OUT) を持っているため、ほとんどのインテル iAPx86 の実装では通常のアドレス空間の一部ではありません

しかし、とにかく簡単な話をしましょう。CPU が ‘1111111111111111111110000’ を欲しがっていて、’1111110000′ ラインだけが接続されていても、それは CPU には同じです

1  HRH Sven Olaf von CyberBunker  2020-01-30


ハードウェアのアドレス空間が増えても、Biosプログラムを更新する必要がないから。バイオス上のメモリ自体が増えても、バイオスコードを更新する必要がない。これは、アドレスデコーダがVCCまで引っ張らないとアドレスバスがグランドに引っ張られて1になってしまうという事実を利用したものです。論理的には1が電気的に0になり、アドレスバス上では論理的に0が電気的に1になる

-1  Harry Helm  2020-08-04


タイトルとURLをコピーしました