Der größte Teil des Inhalts dieser Antwort stammte ursprünglich von dieser Antwort (geschrieben vor dieser anderen Frage, die als Duplikat gekennzeichnet war). Ich diskutiere also die Verwendung von 8-Bit-Werten (auch wenn in dieser Frage nach 32-Bit-Werten gefragt wurde), aber das ist in Ordnung, denn 8-Bit-Werte sind konzeptionell einfacher zu verstehen, und dieselben Konzepte gelten auch für größere Werte wie die 32-Bit-Arithmetik.
Wenn Sie zwei Zahlen addieren, die 8 Bit sind, erhalten Sie die größte Zahl, die Sie erhalten können (0xFF + 0xFF = 1FE). Wenn Sie zwei 8-Bit-Zahlen multiplizieren, beträgt die größte Zahl, die Sie erhalten können (0xFF * 0xFF = 0xFE01), immer noch 16 Bit, also zweimal 8-Bit.
Nun nehmen Sie vielleicht an, dass ein x-Bit-Prozessor nur x-Bits verfolgen kann. (Zum Beispiel kann ein 8-Bit-Prozessor nur 8 Bits verfolgen.) Das ist nicht genau. Der 8-Bit-Prozessor empfängt Daten in 8-Bit-Blöcken (diese “Blöcke” haben normalerweise einen formalen Begriff: ein “Wort”). Auf einem 8-Bit-Prozessor werden 8-Bit-Wörter verwendet. Auf einem 64-Bit-Prozessor können 64-Bit-Wörter verwendet werden)
Wenn Sie dem Computer also 3 Bytes geben:
Byte #1: Die MUL-Anweisung
Byte #2: die Bytes höherer Ordnung (z.B. 0xA5)
Byte #3: die Bytes niedrigerer Ordnung (z.B. 0xCB)
Der Computer kann ein Ergebnis erzeugen, das mehr als 8 Bits beträgt. Die CPU kann Ergebnisse wie dieses erzeugen:
0100 0000 0100 0010 xxxx xxxx xxxx xxxx xxxx 1101 0111
alias:
0x4082xxxxxxD7
Lassen Sie mich das für Sie interpretieren:
0x bedeutet lediglich, dass die folgenden Ziffern hexadezimal sind.
Auf die “40” werde ich gleich noch näher eingehen.
82 ist Teil des “A”-Registers, das eine Folge von 8 Bits ist.
xx und xx sind Teil von zwei weiteren Registern, die als “B”-Register und “C”-Register bezeichnet werden. Der Grund dafür, daß ich diese Bits nicht mit Nullen oder Einsen aufgefüllt habe, liegt darin, daß ein “ADD”-Befehl (an die CPU gesendet) dazu führen kann, daß diese Bits durch den Befehl unverändert bleiben (während die meisten anderen Bits, die ich in diesem Beispiel verwende, mit Ausnahme einiger der Flagbits verändert werden können).
D7 würde in mehr Bits passen, die als “D”-Register bezeichnet werden.
Das “A”-Register ist nur ein Stück Speicher. Register sind in die CPUs eingebaut, so dass die CPU auf Register zugreifen kann, ohne mit dem Speicher auf einem RAM-Stick interagieren zu müssen.
Das mathematische Ergebnis von 0xA5 mal 0xCB ist also 0x82D7.
Warum wurden die Bits nun in die Register A und D aufgeteilt, anstatt in die Register A und B oder in die Register C und D? Nun, noch einmal, dies ist ein Beispielszenario, das ich benutze und das vom Konzept her einer echten Assemblersprache (Intel x86 16-Bit, wie sie von den Intel 8080 und 8088 und vielen neueren CPUs verwendet wird) ziemlich ähnlich sein soll. Es könnte einige gemeinsame Regeln geben, wie z.B. das “C”-Register, das typischerweise als Index für Zähloperationen verwendet wird (typisch für Schleifen), und das “B”-Register, das zur Verfolgung von Offsets verwendet wird, die bei der Angabe von Speicherplätzen helfen. Daher könnten “A” und “D” für einige der üblichen arithmetischen Funktionen gebräuchlicher sein.
Jeder CPU-Befehl sollte eine Dokumentation haben, die von Leuten verwendet wird, die in der Baugruppe programmieren. Diese Dokumentation sollte angeben, welche Register von jeder Anweisung verwendet werden. (Die Wahl, welche Register verwendet werden sollen, wird also oft von den Entwicklern der CPU festgelegt, nicht von den Assembler-Programmierern. Obwohl es eine gewisse Flexibilität geben kann)
Nun zurück zu den “40” im obigen Beispiel: das ist eine Reihe von Bits, oft als “Flags-Register” bezeichnet. Jedes Bit im Flags-Register hat einen Namen. Zum Beispiel gibt es ein “Überlauf”-Bit, das die CPU setzen kann, wenn das Ergebnis größer ist als der Platz, der ein Byte des Ergebnisses speichern kann. (Das “Überlauf”-Bit kann oft mit dem abgekürzten Namen “OF” bezeichnet werden. Das ist ein großes o, keine Null). Software kann auf den Wert dieses Flags prüfen und das “Problem” bemerken. Die Arbeit mit diesem Bit wird oft unsichtbar von höheren Sprachen gehandhabt, so dass Anfänger oft nicht lernen, wie mit den CPU-Flags zu interagieren ist. Assembler-Programmierer greifen jedoch häufig auf einige dieser Flags auf eine Art und Weise zu, die anderen Variablen sehr ähnlich ist.
Zum Beispiel könnten Sie mehrere ADD-Befehle haben. Ein ADD-Befehl könnte 16 Bit Ergebnisse im A-Register und im D-Register speichern, während ein anderer Befehl nur die 8 niedrigen Bits im A-Register speichert, das D-Register ignoriert und das Überlaufbit spezifiziert. Dann könnten Sie später (nach dem Speichern der Ergebnisse des A-Registers im Haupt-RAM) einen weiteren ADD-Befehl verwenden, der nur die 8 hohen Bits in einem Register (möglicherweise dem A-Register) speichert. Ob Sie ein Überlauf-Flag verwenden müssen, hängt möglicherweise davon ab, welchen Multiplikationsbefehl Sie verwenden.
(Üblicherweise gibt es auch ein “Unterlauf”-Flag, falls Sie zu viel subtrahieren, um in das gewünschte Ergebnis zu passen.)
Nur um Ihnen zu zeigen, wie kompliziert die Dinge wurden:
Der Intel 4004 war eine 4-Bit-CPU
Der Intel 8008 war eine 8-Bit-CPU. Er hatte 8-Bit-Register mit den Namen A, B, C und D.
Der Intel 8086 war eine 16-Bit-CPU. Er verfügte über 16-Bit-Register namens AX, BX, CX und DX.
Der Intel 80386 war eine 32-Bit-CPU. Er hatte 32-Bit-Register mit den Namen EAX, EBX, ECX und EDX.
Die Intel x64-CPUs hatten 64-Bit-Register mit den Namen RAX, RBX, RCX und RDX. Die x64-Chips können 16-Bit-Code ausführen (in einigen Betriebsarten) und 16-Bit-Befehle interpretieren. Dabei sind die Bits, aus denen das AX-Register besteht, die Hälfte der Bits, aus denen das EAX-Register besteht, die die Hälfte der Bits sind, aus denen das RAX-Register besteht. Jedes Mal, wenn Sie also den Wert von AX ändern, ändern Sie auch EAX und RAX, da die von AX verwendeten Bits Teil der von RAX verwendeten Bits sind. (Wenn Sie EAX um einen Wert ändern, der ein Vielfaches von 65.536 ist, bleiben die niedrigen 16 Bits unverändert, so dass AX sich nicht ändern würde. Wenn Sie EAX um einen Wert ändern, der kein Vielfaches von 65.536 ist, dann würde sich das auch auf AX auswirken)
Es gibt mehr Flags und Register als nur die von mir erwähnten. Ich habe einfach einige gebräuchliche ausgewählt, um ein einfaches konzeptionelles Beispiel zu geben.
Nun, wenn Sie auf einer 8-Bit-CPU arbeiten und in den Speicher schreiben, finden Sie vielleicht einige Einschränkungen bezüglich der Möglichkeit, sich auf eine Adresse von 8 Bits zu beziehen, nicht auf eine Adresse von 4 Bits oder 16 Bits. Die Einzelheiten hängen von der CPU ab, aber wenn Sie solche Einschränkungen haben, dann kann es sein, dass die CPU mit 8-Bit-Wörtern zu tun hat, weshalb die CPU am häufigsten als “8-Bit-CPU” bezeichnet wird.