it-swarm.com.de

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

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.

50

0xFFFFFFF0 ist der Punkt, an dem eine x86-kompatible CPU beim Einschalten Anweisungen ausführt. Dies ist ein festverdrahteter, unveränderlicher Aspekt (ohne zusätzliche Hardware) der CPU, und verschiedene CPU-Typen verhalten sich unterschiedlich.

Warum befindet sich der erste BIOS-Befehl oben auf einem 4-GB-RAM?

Es befindet sich im "oberen" Bereich von 4 GB Adressraum - und beim Einschalten des BIOS oder UEFI ROM reagiert auf Lesevorgänge dieser Adressen.

Meine Theorie, warum das so ist:

Fast alles in der Programmierung funktioniert besser mit zusammenhängenden Adressen. 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, der kein MMU hatte.

In der 8086 existierten Unterbrechungsvektoren an der Speicherstelle 0 und darüber. Interrupt-Vektoren müssen an bekannten Adressen sein und sollten sich aus Gründen der Flexibilität in RAM befinden. Allerdings war es dem CPU-Designer nicht möglich zu wissen, wie viel RAM sich in a befinden würde System. Es machte also Sinn, mit 0 anzufangen, und diese aufzurüsten (da kein System im Jahr 1978, als der 8086 erfunden wurde, 4 GByte an RAM hatte - es war also nicht sinnvoll, zu erwarten, dass RAM bei 0xFFFFFFF0 liegt) eine gute Idee), und dann müsste ROM an der oberen Grenze sein.

Ab mindestens 80286 könnten Interrupt-Vektoren an einen anderen Startort 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 also 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 und RAM in anderen leben. Mit dem 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.)?

Einfach ausgedrückt: 64-Bit-CPUs haben mehr Adressen (was zu den 64-Bit-Adressen gehört, z. B. 0x0000000000000000 bis 0xFFFFFFFFFFFFFFFFFF), sodass das zusätzliche RAM "passt". Angenommen, die CPU befindet sich im langen Modus . Bis dahin ist das 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 nicht sofort feststellen, was x86 dem Stapelzeiger beim Einschalten zuweist, aber es müsste schließlich ohnehin von einer Initialisierungsroutine neu zugewiesen werden, sobald diese Routine feststellt, wie viel RAM sich im System befindet . (@Eric Towers in den Kommentaren unten meldet, dass es beim Einschalten auf Null gesetzt wird.)

55
LawrenceC

Es befindet sich nicht oben im RAM. Es befindet sich in ROM, dessen Adresse sich oben im Adressraum des Speichers befindet, zusammen mit dem Speicher auf Erweiterungskarten, 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 mindestens 4 GB RAM können den Konflikt auf zwei Arten lösen. Günstige Motherboards ignorieren einfach die Teile von RAM, die im Konflikt mit der Position von ROM stehen. Anständige ordnen neu zu, dass RAM anscheinend eine Adresse über der 4-GB-Marke hat.

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 in 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 Stapel einzurichten (einen pro Task/Thread).

25
psusi

Erstens hat das eigentlich nichts mit RAM zu tun. Wir sprechen hier vonAdressraum- selbst wenn Sie nur 16 MB Speicher haben, haben Sie immer noch die vollen 32 Bit Adressraum auf einer 32-Bit-CPU.

Dies beantwortet bereits Ihre erste Frage - zu der Zeit, als diese entwickelt wurde, hatten echte PCs nicht annähernd die vollen 4 GiB 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 Zuordnung des Adressraums - die Adresse wird direkt in den BIOS-Chip ROM abgebildet (ja, dies bedeutet, dass Sie nicht auf die vollständigen 4 GiB zugreifen können RAM an diesem Punkt, wenn Sie so viele haben - aber das ist nichts Besonderes, viele Geräte benötigen einen eigenen Bereich im Adressraum). Auf einer 32-Bit-CPU stehen Ihnen mit dieser Adresse 16 Byte für die grundlegende Initialisierung zur Verfügung. Dies reicht aus, um Ihre Segmente und bei Bedarf den Adressmodus einzurichten (denken Sie daran, dass x86 im 16-Bit-Realmodus startet - den Adressraum) ist nicht flach) und springe zurealboot "procedure". Zu diesem Zeitpunkt verwenden Sie überhaupt nicht RAM - es ist alles nur ein zugeordnetes ROM. Tatsächlich ist 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? Klar, 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 Zugriff auf den High-Adressraum erhalten (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 Sichtweise ergibt sich 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 in das Display schreiben möchten, haben Sie direkt an die Adresse B800:0000 geschrieben (plus Versatz - im 80x25-Textmodus bedeutet dies (y * 80 + x) * 2, wenn mein Speicher richtig funktioniert - zwei Bytes pro Zeichen, zeilenweise). Wenn Sie pixelweise zeichnen möchten, haben Sie einen Grafikmodus und die Startadresse A000:0000 verwendet (normalerweise 320 x 200 bei 8 Bit pro Pixel). 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. Unter 32-Bit werden Sie feststellen, dass die meisten dieser Geräte über der Marke 2 GiB (später 3 GiB) zugeordnet sind, um Konflikte mit dem nutzbaren Speicher zu minimieren, obwohl dies nicht wirklich der Fall ist ein Problem mit dem virtuellen Speicher (Anwendungen kommen nicht in die Nähe desreal, HardwareAdressraums - sie haben ihren eigenen virtualisierten Speicherbereich, der möglicherweise dem RAM zugeordnet ist, ROM, Geräte oder die Auslagerungsdatei, zum Beispiel).

Was den Stapel angeht, sollte es hilfreich sein, zu verstehen, dass der Stapel standardmäßig von oben wächst. Wenn Sie also eine Push ausfü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 zuvor sicher verwenden können Remapping es 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 selbst die modernste x86-64-CPUMS DOS 5 noch booten kann- oder wie Windows noch viele DOS-Anwendungen ausführen kann, die keine Ahnung von Paging haben.

13
Luaan

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 [für einige Embedded-Controller durchaus plausibel] benötigt, wird möglicherweise das RAM für aktiviert alle Adressen, bei denen die oberste Adressleitung niedrig war, und das ROM für alle Adressen, bei denen es hoch war. 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 verbleibenden 11 Adreßleitungen wären einfach mit nichts verbunden.

Auf einem solchen Computer wären Zugriffe auf die Adressen 0x00100000-0x001FFFFF gleichbedeutend mit Zugriffen auf 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 Anordnen des Rücksetzvektors in der Nähe des oberen Bereichs des Adressraums ist ein Entwurf, der gut funktioniert, unabhängig davon, wie viel oder wie wenig RAM und ROM das System hat und die Notwendigkeit einer vollständigen Dekodierung vermeidet der Adressraum.

7
supercat

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 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 einzelnen 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 ...

3
Agguro

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 von 2000 US-Dollar handelt, mit der die Startadresse (die absolute entfernte JMP, unabhängig von der Position, in diesem Fall innerhalb der 8-KB-ROM selbst, jedoch nicht die niedrigstmögliche Adresse innerhalb dieser ROM) auf $ FFFF gesetzt wird: $ 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 genau 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".

Das Motherboard stellt sicher, dass die Anweisung 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.

1
viktorkh