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.
Antworten:
0xFFFFFFF0
Hier 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.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.
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.
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.
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.)
quelle
0xFFFFFFF0
ist 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 bei0xFFFF0
.0xFFFF0
, aber in Wirklichkeit ist es so0xFFFFFFF0
. 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 werden0xFFFF0
, aber die 32-Bit-CPUs greifen tatsächlich zu0xFFFFFFF0
(dem BIOS-ROM zugeordnet).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).
quelle
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:0000
möchten , haben Sie direkt an die Adresse geschrieben (plus Versatz - im 80x25-Textmodus bedeutet dies,(y * 80 + x) * 2
wenn mein Speicher richtig funktioniert - zwei Bytes pro Zeichen, Zeile für Zeile). Wenn Sie pixelweise zeichnen möchten, haben Sie einen Grafikmodus und die StartadresseA000: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
push
ausführen, befindet sich der neue Stapelzeiger auf0xFFFFFEC
- 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.quelle
0xFFFFFFEC
gemappt werden würde). Das heißt nicht nur nein,push
sondern zum Beispiel auch neincall
. Diese müssen warten, bis der Arbeitsspeicher bereit ist.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.
quelle
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 ...
quelle
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
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".
quelle
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.
quelle