Frage:
Grund für den x86-Rücksetzvektor ist 0xFFFFFFF0 anstelle von 0xFFFFFFFF
Melab
2020-07-06 03:19:35 UTC
view on stackexchange narkive permalink

Die beste Antwort auf diese Frage auf Super User gab eine Erklärung, die für mich zunächst zufriedenstellend war, warum sich der Rücksetzvektor nicht an Adresse 0 befindet (danach wurde mir klar, dass dies nicht der Fall istwarum das Ende des RAM nicht auf 0xFFFFFFFF gesetzt werden konnte und dann nach unten wächst).Aber 0xFFFFFFF0 ist so eine seltsame Adresse.Warum wird x86 mit 16 Byte vor dem oberen Rand des 32-Bit-Adressraums ausgeführt?Werden diese 16 Bytes für etwas Besonderes verwendet?

Zwei antworten:
nanofarad
2020-07-06 03:24:46 UTC
view on stackexchange narkive permalink

x86-Befehle belegen häufig mehr als ein Byte, und eine vernünftige Rücksetzroutine weist mit ziemlicher Sicherheit auf mehrere Befehle hin.

Wenn sich der Rücksetzvektor auf 0xFFFF_FFFF beziehen würde, würde nur ein einzelner Bytebefehl in diese Speicherzuordnung passen;Fast jede nützliche Rücksetzfunktion würde daher Anweisungen erfordern, die die lineare Adressgrenze 0xFFFF_FFFF / 0xFFFF_0000 überschreiten (da das Codesegment mit der Basis 0xFFFF_0000 eingerichtet ist)

Wenn Sie den Rücksetzcode an dieser Adresse platzieren, können Sie einige Anweisungen (einschließlich eines Sprungs) eingeben, ohne dass bei 0xFFFF_0000 ein gültiger Speicher erforderlich ist.

Selbst für einen Sprung wäre eine Mindestgröße 2 Bytes, und ein Sprung ist die einzige nützliche Anweisung, die in einen so kleinen Raum passen könnte.
@ChrisStratton, danke, machte eine schnelle Lösung für die Terminologie
Einige mögliche Initialisierungsroutinen: cli;jmp far .... (6 Bytes);cli;cld;mov axe, 0xFFFF, mov ds, axe, jmp far [adresse] (12 bytes).Als ich ein Bios aus der Ära 2001 zerlegte, verwendete es eine andere Variante eines Sprungtisches.
@Joshua Intel-Programmierhandbücher sagen, dass es normalerweise nichts weiter als einen Sprung gibt, und es ist typischerweise ein 5-Byte-FAR-Sprung.Zu diesem Zeitpunkt sollte es keinen Grund für eine andere Art von Startcode geben, außer für einen Sprung.IBM hat einen FAR-Sprung ausgeführt, und da nicht verwendete Bytes vorhanden waren, folgt der 5-Byte-Sprung einer BIOS-Datumszeichenfolge oder 6 Zeichen und zwei Bytes an Maschinen-ID-Daten.Beachten Sie, dass sich BIOSes aus der Ära 2001 möglicherweise bereits im RAM dekomprimiert haben. Daher stimmt das, was Sie nach dem Booten sehen, möglicherweise nicht mit dem überein, was nach einem Kaltstart physisch vorhanden ist.
@Justme: Das Handbuch ist falsch.Wenn die CLI-Anweisung fehlt, könnte ein Virus die Reset-Taste überleben.
@Joshua CLI-Anweisung ist irrelevant.Die Schaltfläche "Zurücksetzen" gibt der CPU einen Hardware-Reset, der die Ausführung des BIOS-Codes ab einem definierten Zustand startet. Ich versichere Ihnen, dass die Interrupts deaktiviert sind.Nach einem Hardware-Reset steht auch kein RAM zur Verfügung, bis der RAM-Controller initialisiert wird und danach alle Vektoren eingerichtet sind.Keine Chance, dass ein Virus eine Reset-Schaltfläche überlebt, es sei denn, er hat sich selbst in das BIOS geschrieben.Und das ist passiert.
Justme
2020-07-06 14:19:20 UTC
view on stackexchange narkive permalink

Der Grund, warum es 16 Byte unter dem oberen Rand des Speichers liegt, liegt darin, wie die ursprünglichen 8086-CPU-Register beim Zurücksetzen geladen wurden. Und selbst das hat möglicherweise etwas mit der Kompatibilität für ältere 8085-CPUs zu tun. Diese Kompatibilität wurde auf spätere Chips wie 80286, 80386 usw. übertragen.

Sicher, sie hätten einen beliebigen Wert auswählen können, aber da Interrupt-Vektoren am unteren Rand des Speicherbereichs festgelegt sind, in dem RAM gespeichert werden soll, soll das Programm-ROM oben im Speicherbereich platziert werden.

Während eine beliebige Adresse oben im Speicher ausgewählt werden kann, ist es sinnvoll, so nah wie möglich an den letzten Speicheradressen zu sein, damit nicht festgelegt wird, wie groß der ROM-Bereich sein muss, und Sie können als verwenden kleines ROM wie möglich.

Und es darf auch nicht zu nahe an der letzten Speicheradresse liegen, um genügend Platz für Anweisungen bereitzustellen, um zumindest zu springen und Code an einer anderen Stelle auszuführen. Ein Opcode für einen kurzen Sprung besteht aus zwei Bytes, ein Nahsprung aus drei Bytes und der Weitsprung aus 5 Bytes. Daher ist es sinnvoll, mindestens 5 Bytes für den Bereich zu reservieren.

Da der 8086 über einen 20-Bit-Adressraum (oder 1 Megabyte) verfügt und von den Designern ausgewählt wurde, wird ein segmentierter Speicheransatz verwendet, bei dem Sie ein 16-Bit-Segment und einen 16-Bit-Offset verwenden, um auf eine lineare 20-Bit-Adresse zu verweisen . Dies bedeutet, dass jedes Segmentregister eine Basisadresse für einen 16-Bit-Offset mit einer Basisadressengranularität von 16 Bytes auswählen kann. Grundsätzlich wurde die Adressierung des 16-Bit-8085 nur um Segmentregister erweitert.

Während des Zurücksetzens der Hardware wird das IP-Register (Program Counter) wie bei einer 8085-CPU auf 0x0000 gesetzt. Und um an das Ende des Speichers zu gelangen, wird das CS-Register (Code Segment) auf 0xFFFF gesetzt. Dadurch startet die CPU ab 16 Byte am Ende des Speichers.

Es gibt viele gültige CS: IP-Kombinationen, die sich zur linearen Adresse von 0xFFFF0 addieren, aber dies war höchstwahrscheinlich die einfachste Methode, da alle Bits im Register mit demselben Wert geladen werden, IP mit null Bits und CS mit einem Bit, so dass das Laden einer speziellen Kombination von Bits in eines der beiden Register nicht erforderlich war.

Spätere CPUs haben diese Kompatibilität jedoch bereits etwas gebrochen, aber auf eine Weise, die nicht viel ausmacht.

Beispielsweise lädt ein 80286 das IP-Register mit 0xFFF0. Und da der 24-Bit-Speicherbus für den Zugriff auf 16 MB Speicher verwendet wird und sich das ROM noch am Ende des adressierbaren 16-MB-Speichers befinden muss, wird der CS-Registerwert auf 0xF000 zurückgesetzt, sodass CS: IP im Real-Modus auf zeigt 0xFFFF0, und die CS-Auswahlbasis wird auf die Basisadresse 0xFF0000 gesetzt, um die physische Speicherbasis festzulegen, so dass die physikalische Adresse 0xFFFFF0 ist. Auf diese Weise kann das alte 8086-System, wenn Sie es gerade so umgestaltet haben, dass es einen 80286 enthält, kompatibel gemacht werden, um das ursprüngliche ROM zu starten.

Wenn dies auf das 32-Bit-80386 erweitert wurde, lädt es auch das 32-Bit-IP-Register mit 0x0000FFF0, das CS-Register mit 0xF000 und die CS-Auswahlbasis mit 0xFFFF0000, sodass die physikalische Adresse 0xFFFFFFF0 ist. Wenn also ein 80286-System für eine 80386SX-CPU neu konzipiert wurde, kann es kompatibel gemacht werden, um das ursprüngliche ROM zu starten.



Diese Fragen und Antworten wurden automatisch aus der englischen Sprache übersetzt.Der ursprüngliche Inhalt ist auf stackexchange verfügbar. Wir danken ihm für die cc by-sa 4.0-Lizenz, unter der er vertrieben wird.
Loading...