Warum befindet sich der erste BIOS-Befehl bei 0xFFFFFFF0 ("oben" im RAM)?


51

Ich weiß, dass das BIOS seine erste Anweisung von 0xFFFFFFF0 lädt, aber warum diese spezifische Adresse? Ich habe ein paar Fragen und hoffe, dass Sie mir zumindest bei einigen helfen können.

Meine Fragen:

  • Warum befindet sich der erste BIOS-Befehl oben auf einem 4-GB-RAM?
  • Was würde passieren, wenn mein Computer nur 1 GB RAM hat?
  • Was ist mit Systemen mit mehr als 4 GB RAM (z. B. 8 GB, 16 GB usw.)?
  • Warum wird der Stack mit einem bestimmten Wert initialisiert (in diesem Fall einem Wert, der sich bei 0xFFFFFFF0 befindet)?

Ich habe heute Nachmittag darüber gelesen und verstehe es immer noch nicht.


28
Eine Frage pro Frage bitte.
Leichtigkeit Rennen mit Monica

4
Mir gefällt, dass in der akzeptierten Antwort nicht einmal segmentierte Speicher- oder Adressierungsmodi erwähnt werden und der einzige Punkt, an dem die A20-Leitung überhaupt berührt wird, in den Kommentaren liegt.
Imallett

Atmel-AVRs starten die Ausführung ab Adresse 0, während Freescale HCS08 ab 0xFFFE, iirc startet. Jede Prozessorfamilie hat ihre eigenen Eigenschaften.
Nick T

2
@imallett Mir gefällt, wie Sie sich hier beschweren, anstatt das Poster zu bitten, die Antwort mit weiteren Informationen zu aktualisieren. Mir gefällt auch, wie Sie denken, dass dieses Wissen, das OP erkennen kann, obwohl der Zweck einer Frage darin besteht, Wissen über Dinge zu erlangen, die man jetzt vielleicht vollständig versteht.
MonkeyZeus

2
@MonkeyZeus bis heute haben 9 andere Kommentatoren das bereits getan, und es hat sich immer noch nicht geändert. Mein Kommentar war zwar sarkastisch, aber nicht leer; Es ist eine Warnung an die zukünftigen Internetnutzer sowie an das OP.
Imallett

Antworten:


57

0xFFFFFFF0Hier beginnt eine x86-kompatible CPU mit der Ausführung von Anweisungen, wenn sie eingeschaltet ist. Dies ist ein festverdrahteter, unveränderlicher Aspekt (ohne zusätzliche Hardware) der CPU, und verschiedene CPU-Typen verhalten sich unterschiedlich.

Warum befindet sich die erste BIOS-Anweisung oben auf einem 4-GB-RAM?

Es befindet sich im "oberen" Bereich des 4-GB- Adressraums - und beim Einschalten wird das BIOS oder UEFI- ROM so eingestellt, dass es auf Lesevorgänge dieser Adressen reagiert.

Meine Theorie, warum das so ist:

Fast alles in der Programmierung funktioniert mit zusammenhängenden Adressen besser. Der CPU-Designer weiß nicht, was ein System-Builder mit der CPU machen möchte. Daher ist es eine schlechte Idee, dass die CPU Adressen benötigt, die in der Mitte des Speicherplatzes liegen und für verschiedene Zwecke benötigt werden. Es ist besser, das "aus dem Weg" oben oder unten im Adressraum zu lassen. Denken Sie natürlich daran, dass diese Entscheidung getroffen wurde, als der 8086 neu war und keine MMU besaß .

In der 8086 existierten Unterbrechungsvektoren an der Speicherstelle 0 und darüber. Interrupt-Vektoren müssen an bekannten Adressen vorliegen und sollten sich aus Gründen der Flexibilität im RAM befinden. Dem CPU-Designer war es jedoch nicht möglich zu wissen, wie viel RAM sich in einem System befinden würde. Es machte also Sinn, mit 0 anzufangen, und diese aufzurüsten (da 1978, als der 8086 erfunden wurde, kein System 4 GB RAM hatte - es war also keine gute Idee, RAM auf 0xFFFFFFF0 zu setzen), und dann musste es ROM sein an der oberen Grenze.

Ab mindestens 80286 könnten Interrupt-Vektoren an eine andere Startposition als 0 verschoben werden, aber moderne 64-Bit-x86-CPUs werden weiterhin im 8086-Modus gestartet, sodass aus Kompatibilitätsgründen immer noch alles auf die alte Weise funktioniert (was lächerlich ist) wie es sich im Jahr 2015 anhört, muss Ihre x86-CPU noch DOS ausführen können).

Da Interrupt-Vektoren bei 0 beginnen und aufwärts arbeiten, müsste ROM von oben beginnen und abwärts arbeiten.

Was würde passieren, wenn mein Computer nur 1 GB RAM hat?

Eine 32-Bit-CPU hat 4.294.967.296 Adressen mit den Nummern 0 (0x00000000) bis 4294967295 (0xFFFFFFFF). ROM kann in einigen Adressen leben und RAM kann in anderen leben. Mit der MMU der CPU kann dies sogar im laufenden Betrieb umgeschaltet werden. RAM muss nicht an allen Adressen leben.

Mit nur 1 GB RAM reagieren einige Adressen beim Lesen oder Schreiben nicht. Dies kann dazu führen, dass ungültige Daten gelesen werden, wenn auf solche Adressen zugegriffen wird oder das System abstürzt.

Was ist mit Systemen mit mehr als 4 GB RAM (z. B. 8 GB, 16 GB usw.)?

Einfacher ausgedrückt: 64-Bit-CPUs haben mehr Adressen (das ist eines der Dinge, die sie zu 64-Bit-CPUs machen - z. B. 0x00000000000000 bis 0xFFFFFFFFFFFFFFFFFF), sodass das zusätzliche RAM "passt". Angenommen, die CPU befindet sich im Long-Modus . Bis dahin ist der RAM da, nur nicht adressierbar.

Warum wird der Stack mit einem bestimmten Wert initialisiert (in diesem Fall einem Wert, der sich bei 0xFFFFFFF0 befindet)?

Ich kann beim Einschalten nicht sofort feststellen, was x86 dem Stapelzeiger zuweist, aber irgendwann müsste er von einer Initialisierungsroutine neu zugewiesen werden, sobald diese Routine feststellt, wie viel RAM im System vorhanden ist. (@Eric Towers in den Kommentaren unten meldet, dass es beim Einschalten auf Null gesetzt wird.)


7
Stellen Sie sich den Adressraum am besten als einen großen Raum vor, in dem Dinge durch Hardware zugewiesen werden können. Wenn die CPU Speicher liest / schreibt, führt sie tatsächlich eine Kommunikation über einen Bus durch, und die Hardware kann sicherstellen, dass Dinge wie RAM oder ROM in bestimmten Adressbereichen reagieren. Eine solche Hardware müsste also sicherstellen, dass ein ROM auf 0xFFFFFFF0 reagiert, wenn die CPU zurückgesetzt wird. Es besteht keine inhärente Verpflichtung, dass das ROM direkt nach dem RAM angezeigt wird. Es kann überall dort angezeigt werden, wo es die Hardware sagt, abhängig von den Fähigkeiten dieser Hardware.
LawrenceC

4
Es ist möglich, dass "Löcher" oder nicht zugewiesene Speicherplätze vorhanden sind, die nicht von ROM, RAM oder irgendetwas verwendet werden. Wenn Sie auf diese zugreifen, kommt es normalerweise zu einer Systemblockierung.
LawrenceC

16
Diese Antwort setzt voraus, dass die CPU im 16-Bit-Modus 32 Adressbits verwenden kann. Im 16-Bit-Modus können jedoch nur 20 Adressbits verwendet werden. Die Adresse 0xFFFFFFF0ist erst nach dem Umschalten der CPU in den 32-Bit-Modus erreichbar. Das letzte Mal, als ich mir den BIOS-Code genauer ansah, befand sich der Einstiegspunkt bei 0xFFFF0.
Kasperd

6
@ MichaelKjörling deine berechnung ist falsch. Verschobenes Segment und Versatz werden nicht ODER-verknüpft, sondern hinzugefügt. Somit ist logisch FFFF: FFF0 physikalisch (1) 0FFE0 (wobei führende 1 vorhanden ist, wenn A20 aktiviert ist).
Ruslan

9
@kasperd Es gibt einen Hack - der Speichermanager hat die hohen 12 Bits auf 1 gesetzt, bis der erste Weitsprung stattfindet. Also ja, logischerweise arbeitest du damit 0xFFFF0, aber in Wirklichkeit ist es so 0xFFFFFFF0. Ich gehe davon aus, dass dies aus Gründen der Kompatibilität mit dem 8086 geschehen ist - sowohl es als auch modernere CPUs scheinen verwendet zu werden 0xFFFF0, aber die 32-Bit-CPUs greifen tatsächlich zu 0xFFFFFFF0(dem BIOS-ROM zugeordnet).
Luaan

26

Es befindet sich nicht oben im RAM. Es befindet sich im ROM, dessen Adresse sich oben im Adressraum des Speichers befindet, zusammen mit dem Speicher auf Erweiterungskarten, wie z. B. Ethernet-Controllern. Es ist vorhanden, damit es nicht zu Konflikten mit dem Arbeitsspeicher kommt, zumindest bis Sie 4 GB installiert haben. Systeme mit 4 GB oder mehr RAM können den Konflikt auf zwei Arten lösen. Günstige Motherboards ignorieren einfach die RAM-Teile, die mit dem ROM-Speicher in Konflikt stehen. Anständige ordnen dem RAM eine Adresse zu, die über der 4-GB-Marke liegt.

Ich bin nicht sicher, was Sie über den Stapel fragen. Es ist sicherlich nicht initialisiert, um im ROM zu sein. Wenn die CPU zurückgesetzt wird, befindet sie sich anfangs im "Real-Modus", in dem sie sich wie die ursprüngliche 8086 verhält und eine segmentierte 16-Bit-Adressierung verwendet, sodass sie nur auf 1 MB Speicher zugreifen kann. Der BIOS-Code befindet sich oben auf dieser 1 MB. Das BIOS wählt irgendwo im RAM aus, um den Stack einzurichten, lädt den ersten Sektor des ersten bootfähigen Laufwerks und führt ihn aus. Es ist Aufgabe des Betriebssystems, nach der Übernahme in den 32- oder 64-Bit-Modus zu wechseln und eigene Stacks einzurichten (einen pro Task / Thread).


1
Vielen Dank für die Antwort, aber @LawrenceC gibt weitere Details zu seiner Antwort und hat mir geholfen, wie das Ganze funktioniert. Trotzdem danke! Ich gebe Ihnen eine positive Bewertung: 3
Fernando Paladini

13

Erstens hat das eigentlich nichts mit RAM zu tun. Wir sprechen hier über den Adressraum - auch wenn Sie nur 16 MB Speicher haben, haben Sie immer noch die vollen 32 Bits des Adressraums auf einer 32-Bit-CPU.

Damit ist Ihre erste Frage bereits beantwortet - zu der Zeit, als diese entwickelt wurde, hatten PCs der realen Welt noch nicht annähernd die vollen 4 GB Speicher; Sie lagen eher im Bereich von 1-16 MiB Speicher. Der Adressraum war in jeder Hinsicht frei.

Warum genau 0xFFFFFFF0? Die CPU weiß nicht, wie viel vom BIOS vorhanden ist. Einige BIOS-Versionen benötigen möglicherweise nur ein paar Kilobyte, während andere möglicherweise volle Megabyte an Arbeitsspeicher beanspruchen - und ich komme nicht einmal in die verschiedenen optionalen RAMs. Die CPU muss auf eine bestimmte Adresse fest verdrahtet sein, um zu starten - es gibt keine Töne, um die CPU zu konfigurieren. Dies ist jedoch nur eine Abbildung des Adressraums - die Adresse wird direkt in den BIOS-ROM-Chip abgebildet (ja, dies bedeutet, dass Sie zu diesem Zeitpunkt nicht auf die vollen 4 GB RAM zugreifen können, wenn Sie über so viele verfügen - aber Das ist nichts Besonderes. Viele Geräte benötigen einen eigenen Adressraum. Auf einer 32-Bit-CPU erhalten Sie mit dieser Adresse volle 16 Byte für die grundlegende Initialisierung. Dies reicht aus, um Ihre Segmente und bei Bedarf den Adressmodus einzurichten (denken Sie daran,echte Boot "Verfahren". Zu diesem Zeitpunkt wird kein RAM verwendet, sondern nur ein zugeordnetes ROM. Tatsächlich ist der RAM zu diesem Zeitpunkt noch nicht einmal einsatzbereit - das ist eine der Aufgaben des BIOS-POST! Sie denken jetzt vielleicht: Wie greift ein 16-Bit-Real-Modus auf die Adresse 0xFFFFFFF0 zu? Sicher, es gibt Segmente, Sie haben also einen 20-Bit-Adressraum, aber das ist immer noch nicht gut genug. Nun, es gibt einen Trick: Die 12 High-Bits der Adresse werden gesetzt, bis Sie Ihren ersten Weitsprung ausführen, wodurch Sie auf den High-Adressraum zugreifen können (während Sie den Zugriff auf weniger als 0xFFF00000 ablehnen - bis Sie einen Weitsprung ausführen). .

All dies sind die Dinge, die Programmierern (von Benutzern ganz zu schweigen) auf modernen Betriebssystemen meist verborgen bleiben. Normalerweise haben Sie keinen Zugriff auf etwas so Niedriges - einige Dinge sind bereits nicht mehr zu retten (Sie können den CPU-Modus nicht ohne Weiteres wechseln), andere werden ausschließlich vom Betriebssystemkern verwaltet.

Eine schönere Sicht ergibt sich also aus der alten Programmiersprache unter MS DOS. Ein weiteres typisches Beispiel für Gerätespeicher, der direkt dem Adressraum zugeordnet ist, ist der direkte Zugriff auf den Videospeicher. Wenn Sie beispielsweise schnell Text auf das Display schreiben B800:0000möchten , haben Sie direkt an die Adresse geschrieben (plus Versatz - im 80x25-Textmodus bedeutet dies, (y * 80 + x) * 2wenn mein Speicher richtig funktioniert - zwei Bytes pro Zeichen, Zeile für Zeile). Wenn Sie pixelweise zeichnen möchten, haben Sie einen Grafikmodus und die Startadresse A000:0000(normalerweise 320 x 200 bei 8 Bit pro Pixel) verwendet. Wenn Sie etwas Hochleistungsfähiges tun, müssen Sie in Gerätehandbüchern nachschlagen, um herauszufinden, wie Sie direkt darauf zugreifen können.

Dies überlebt bis heute - es ist nur versteckt. Unter Windows können Sie die den Geräten zugewiesenen Speicheradressen im Geräte-Manager anzeigen. Öffnen Sie dazu einfach die Eigenschaften Ihrer Netzwerkkarte und wechseln Sie zur Registerkarte Ressourcen. Bei allen Speicherbereichselementen handelt es sich um Zuordnungen vom Gerätespeicher zum Hauptadressraum. Bei 32-Bit-Versionen werden Sie feststellen, dass die meisten dieser Geräte oberhalb der 2-GiB- (später 3-GiB-) Marke zugeordnet sind, um Konflikte mit dem nutzbaren Speicher zu minimieren. Dies ist jedoch kein wirkliches Problem mit dem virtuellen Speicher ( Anwendungen kommen nicht an den realen Hardware- Adressraum heran - sie verfügen über einen eigenen virtualisierten Speicherbereich, der beispielsweise auf RAM, ROM, Geräte oder die Auslagerungsdatei abgebildet werden kann.

Was den Stapel angeht, sollte es hilfreich sein, zu verstehen, dass der Stapel standardmäßig von oben wächst. Wenn Sie also a pushausführen, befindet sich der neue Stapelzeiger auf 0xFFFFFEC- mit anderen Worten, Sie versuchen nicht, in die BIOS-Init-Adresse zu schreiben :) Dies bedeutet natürlich, dass die BIOS-Init-Routinen den Stapel sicher verwenden können, bevor Sie ihn neu zuordnen irgendwo nützlicher. Bei der Programmierung in der alten Schule wurde der Stapel normalerweise am Ende des Arbeitsspeichers gestartet, bevor das Auslagern zum De-facto-Standard wurde, und ein "Stapelüberlauf" trat auf, als Sie begannen, den Anwendungsspeicher zu überschreiben. Der Speicherschutz hat sich stark verändert, aber im Allgemeinen bleibt die Abwärtskompatibilität so weit wie möglich erhalten. Beachten Sie, dass auch die modernste x86-64-CPU MS DOS 5 noch booten kann - oder wie Windows immer noch viele DOS-Anwendungen ausführen kann, die keine Ahnung vom Paging haben.


3
Hervorragende Antwort, um nur zu erweitern und zu sagen, dass moderne Prozessoren beginnen, Hacks wie die A20-Linienmaskierung fallen zu lassen , so dass die Unterstützung für ältere Edge-Cases nachlässt.
Basic

2
Zum letzten Absatz: Das BIOS kann den Stack nicht "frei" verwenden: Es kann nicht in das ROM schreiben (auf das 0xFFFFFFECgemappt werden würde). Das heißt nicht nur nein, pushsondern zum Beispiel auch nein call. Diese müssen warten, bis der Arbeitsspeicher bereit ist.
The Vee

7

Zusätzlich zu den anderen genannten Punkten kann es hilfreich sein zu verstehen, was eine Adresse ist . Während neuere Architekturen die Dinge komplizieren, gab eine Maschine in der Vergangenheit in jedem Speicherzyklus die gewünschte Adresse auf 20 bis 32 Drähten aus (abhängig von der Architektur, mit einigen speziellen Tricks, um festzustellen, ob ein Paar oder vier Bytes gleichzeitig benötigt werden); Verschiedene Teile des Speichersystems untersuchten den Zustand dieser Drähte und aktivierten sich, wenn sie bestimmte Kombinationen von hohen und niedrigen Werten sahen.

Wenn ein Computer mit 32 Adreßkabeln nur 1 MB RAM und 64 KB ROM benötigen würde (was für einige eingebettete Controller durchaus plausibel ist), könnte er den RAM für alle Adressen aktivieren, bei denen die oberste Adreßleitung niedrig war, und den ROM für alle Adressen, bei denen sie niedrig war hoch. Die unteren 20 Adressleitungen würden dann mit dem RAM verbunden, um eines von 1.048.576 Bytes auszuwählen, und die unteren 16 würden ebenfalls mit dem ROM verbunden, um eines von 65.536 Bytes auszuwählen. Die restlichen 11 Adreßleitungen wären einfach mit nichts verbunden.

Auf einem solchen Computer entsprechen Zugriffe auf die Adressen 0x00100000-0x001FFFFF den Zugriffen auf die RAM-Adressen 0x00000000-0x000FFFFF. Ebenso mit den Adressen 0x000200000-0x0002FFFFF oder 0x7FF00000-0x7FFFFFFFF. Adressen über 0x80000000 würden alle ROM lesen, wobei sich ein 64-KB-Muster im gesamten Bereich wiederholt.

Obwohl der Prozessor über einen Adressraum von 4.294.967.296 Byte verfügt, muss die Hardware nicht so viele unterschiedliche Adressen erkennen. Das Platzieren des Rücksetzvektors in der Nähe des oberen Bereichs des Adressraums ist ein Entwurf, der unabhängig davon, wie viel oder wie wenig RAM und ROM das System hat, gut funktioniert und die Notwendigkeit vermeidet, den Adressraum vollständig zu decodieren.


Guter Punkt - Sie werden keine 64-Bit-Hardware finden, die irgendetwas in der Nähe des adressierbaren 64-Bit-Speicherplatzes (oder sogar 1x10 ^ -12 davon) unterstützt.
Basic

3

Meine Theorie ist, weil wir negative Logik verwenden, die digitale (1) ist überhaupt keine Spannung (0 Volt). Wir müssen nur die letzten 4 Bits bei der Initialisierung spannen, damit der Programmzähler (oder der Befehlszeiger) bei 1111 1111 abläuft 1111 1111 1111 1111 1111 0000. Wir müssen die oberen 28 Bits nicht adressieren, da die meisten (alten) CPUs) 16 Bits waren und die unteren Nibbles früher mit einem einzigen Adresschip adressiert werden konnten. Jetzt, da wir 64 Bit mit einer Kompatibilität zu 32 Bit und 32 Bit zu 16 Bit haben, wurde die Hardware verbessert, aber die Methode bleibt erhalten. Auch Bios sind nicht immer 64 Bit oder 32 Bit programmiert. Meine Meinung ist auch, da Erinnerungen nicht immer gleich sind, muss sich das BIOS im selben ersten Segment befinden. Die Art und Weise, wie wir das angesprochene BIOS sehen, ist nicht immer die richtige Adresse. Nur ein von mir gelehrter ...


2

Beim RESET führt eine 8088/8086-kompatible CPU die Anweisungen bei 0FFFF0 aus, was 16 Byte unter der 1-Megabyte-Grenze liegt. Normalerweise ist das ROM an dieser Stelle (in PC-Implementierungen) das BIOS. Am Ende des BIOS-ROM befindet sich also ein Sprung zum Start des BIOS-ROM.

Hier gezeigt: Startvektor und 'Datum' Signatur dahinter, IBM 5150 PC 8KB Eprom Dump Bios Datum: 19.10.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

Beachten Sie, dass es sich bei der Adressierung um eine 8-KB-ROM mit einem Wert von 2000 US-Dollar handelt, die die Startadresse (in diesem Fall die absolute JMP-Distanz zu jedem anderen Ort innerhalb der 8-KB-ROM selbst, jedoch nicht die niedrigstmögliche Adresse innerhalb dieser ROM) auf $ FFFF setzt: $ 0 segmentiert oder $ FFFF0 linear.

Aus Kompatibilitätsgründen: Wenn ein "zukünftiger" oder aktueller Prozessor erwartet, dass er viel mehr Fs vor der Adresse hat, spielt das keine Rolle. Aus Gründen der Kompatibilität mit neueren CPUs in älteren Systemen bleiben die zusätzlichen Adressleitungen unverbunden und daher sind die Daten auf dem Datenbus exakt gleich. solange die niedrigstwertigen Bits FFFF0 bleiben.

(In einem System mit nur 1 MB RAM und dem ROM, das am Ende dieses RAM positioniert ist, und sonst nichts, wird es glücklich denken, dass es mit der höheren Adresse spricht, aber die exakt gleichen Daten erhält, weil diese Implementierungen noch nie davon gehört haben Adressleitungen höher als A19)

Beachten Sie, dass die Welt nicht nur "PC" ist ... Der IBM PC war ein "Unfall". Diese Prozessoren wurden nie speziell für "PC" entwickelt und beschäftigen sich mit viel mehr als nur PC (wie Satelliten, Waffensysteme usw.). 32- und 64-Bit-Protected-Modus sind normalerweise nicht erwünscht. (Der virtuelle 8086-Modus ist viel interessanter als ein Grund, sich zum Beispiel für eine neuere (386+) Version zu entscheiden). Daher ist die Abwärtskompatibilität viel mehr als nur "Will it Run Dos".


1

Das Motherboard stellt sicher, dass der Befehl am Rücksetzvektor ein Sprung zum Speicherort ist, der dem BIOS-Einstiegspunkt zugeordnet ist. Dieser Sprung löscht implizit die verborgene Basisadresse, die beim Einschalten vorhanden ist. Alle diese Speicherplätze verfügen dank der vom Chipsatz verwalteten Speicherkarte über die richtigen Inhalte, die von der CPU benötigt werden. Sie sind alle dem Flash-Speicher zugeordnet, der das BIOS enthält, da zu diesem Zeitpunkt die RAM-Module zufälligen Mist enthalten.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.