Ich versuche, in Logisim eine anweisbare 8-Bit-CPU zu entwerfen. Ist es möglich, mit einer 8-Bit-CPU große Zahlen zu berechnen?
In einem 32-Bit-Computer können Sie Zahlen berechnen, die größer als 32-Bit sind. Ich denke, das ist ein Softwaretrick, aber wer kann mir erklären, wie es funktioniert?
Selbst auf 8-Bit- oder 4-Bit-Rechnern ist es durchaus möglich, mit sehr großen Zahlen zu arbeiten. Es ist nicht sehr effizient, aber es ist möglich. Dies geschieht durch stückweise Bearbeitung der Zahlen mit Unterstützung spezifischer Prozessorbefehle.
Ein gängiger 8-Bit-Mikrocontroller ist die Atmel AVR-Serie. Um 8-Bit-Zahlen zu addieren, verwendet es eine Anweisung namens ADD. Dieser Befehl wird verwendet, um zwei Registerwerte zu addieren. Zum Beispiel können Sie tun
LDI R16, 5
LDI R17, 10
ADD R16, R17
; R16 = 15
R16 und R17 addieren und das Ergebnis in R16 eingeben. Um 16-Bit-Zahlen hinzuzufügen, tun Sie dies im Grunde einfach mehrmals. Es gibt jedoch einen Haken: das Carry-Bit. Ein weiterer AVR-Befehl ist ADC, für ADd mit Übertrag. Dies macht genau dasselbe wie ADD, fügt aber auch das Carry-Flag hinzu. Sowohl ADD als auch ADC setzen das Carry-Flag, wenn die Additionsoperation überläuft. Sagen Sie, wenn Sie 128 zu 128 addieren, erhalten Sie als Ergebnis 0 mit gesetztem Carry-Flag. Wenn Sie ADC mit gesetztem Carry-Flag aufrufen, wird dem Ergebnis eine 1 hinzugefügt. Hier ist ein Beispiel für eine 16-Bit-Addition:
LDI R16, 232
LDI R17, 3
; R17:R16 = 1000
LDI R18, 208
LDI R19, 7
; R19:R18 = 2000
ADD R16, R18
ADC R17, R19
; R16 = 184
; R17 = 11
; R17:R16 = 3000
Dies kann so oft wie nötig wiederholt werden, um große Zahlen hinzuzufügen. Beachten Sie, dass ein wenig Logik erforderlich ist, um dies zu unterstützen: die Fähigkeit, das Carry-Flag in den Carry-In des Addierers einzuspeisen.
Ein ähnlicher Prozess kann verwendet werden, um Zahlen zu multiplizieren. Das Durchführen von 16-Bit-Multiplikationen auf einem 8-Bit-Prozessor erfordert 4 8-Bit-Multiplikationen und mehrere Additionen. Das Verfahren ist genau dasselbe wie das Multiplizieren von Zahlen von Hand Ziffer für Ziffer, außer dass Sie Bytes anstelle von Ziffern verwenden. Sie müssen alle vier möglichen Bytepaare multiplizieren und sie dann gemäß ihren Stellenwerten addieren. Beispiel in AVR ASM:
LDI R16, 232
LDI R17, 3
; R17:R16 = 1000
LDI R18, 208
LDI R19, 7
; R19:R18 = 2000
MUL R16, R18
; R1:R0 = R16*R18 (1s place product)
MOVW R3:R2, R1:R0
; R3:R2 = R16*R18
MUL R16, R19
; R1:R0 = R16*R19 (256s place product #1)
CLR R4
ADD R3, R0
ADC R4, R1
; R4:R3:R2 = R16*R18 + 256*R16*R19
MUL R17, R18
; R1:R0 = R17*R18 (256s place product #2)
ADD R3, R0
ADC R4, R1
; R4:R3:R2 = R16*R18 + 256*(R16*R19+R17*R18)
MUL R17, R19
; R1:R0 = R17*R19 (65536s place product)
CLR R5
ADD R4, R0
ADC R5, R1
; R5:R4:R3:R2 = R16*R18 + 256*(R16*R19+R17*R18) + 65536*R17*R19
; R5:R4:R3:R2 = 2000000
Sie werden feststellen, dass Sie genau so mit Zahlen von Hand auf Papier arbeiten, aber anstatt mit Ziffern zur Basis 10 zu arbeiten, arbeitet die CPU mit Blöcken von Bits in Wortgröße - in diesem Fall 8 Bits.
Wenn Sie eine CPU verwenden, die mit mehr Bits gleichzeitig arbeiten kann, wird das Arbeiten mit großen Zahlen einfacher, da weniger Anweisungen erforderlich sind. Sie können jedoch dieselben Techniken verwenden, um mit größeren Zahlen zu arbeiten, als der Befehlssatz direkt unterstützt.
Bearbeiten: Der AVR GCC-Compiler enthält Assembler-Code, den er für verschiedene gängige Operationen wie Multiplikation und Division verwendet, was eine gute Referenz dafür sein kann, wie so etwas gemacht wird: https://github.com/gcc-mirror /gcc/blob/master/libgcc/config/avr/lib1funcs.S . Ich denke, meine Multiplikation von 16x16 zu 32 sollte __umulhisi3 entsprechen.
int
ist 16 Bit), fast mit Makros implementiert, die zu nativen Anweisungen erweitert werden. Daher die ziemlich schlechte Optimierung bei der Registerzuordnung, dem Herummischen (Vorzeichenerweiterung, Byteverschiebung) und der Arithmetik (16x16+ mul/div usw.).Wie Sie sagten, können 32-Bit-CPUs Zahlen verarbeiten, die größer als 32 Bit sind. Warum sollte eine 8-Bit-CPU dies also nicht können?
Wenn Sie zwei Zahlen addieren, beginnen Sie mit dem letzten Bit von beiden. Wenn einer von ihnen 1 ist, ist das Ergebnis 1, wenn beide 1 sind, ist das Ergebnis 0, und Sie müssen eine 1 zur Berechnung des zweiten Bits übertragen.
Für das zweite Bit haben Sie die beiden Bits der Zahlen und das getragene Bit. Wenn einer oder alle drei 1 sind, ist das Ergebnis 1. Wenn zwei oder alle 1 sind, müssen Sie wieder eine 1 zur Berechnung des dritten Bits übertragen.
Dies geschieht normalerweise in Hardware, dh es gibt Logikgatter, Sie geben einfach die Zahlen an die Eingänge und erhalten den Ausgang. Beachten Sie, dass Sie bei einem 8-Bit-Addierer auch das sogenannte Carry-Flag aus der Addition der 8. Bits erhalten.
Wenn Sie nur zwei 8-Bit-Zahlen addieren, zeigt das Carry-Flag nur an, ob das Ergebnis größer als 255 ist, die größte Zahl, die eine 8-Bit-Ganzzahl (ohne Vorzeichen) enthalten kann.
Wenn Sie größere Zahlen haben, beginnen Sie jetzt mit der Addition der Bits des zweiten Bytes und berücksichtigen bei der Addition des ersten Bits dieses Bytes das Carry-Flag aus der vorherigen Addition.
Der einzige Unterschied besteht darin, dass eine 32-Bit-CPU 32 Bit auf einmal hinzufügen kann, sodass das Hinzufügen von 64-Bit-Zahlen aus zwei Schritten besteht, während eine 8-Bit-CPU 8 Schritte benötigt.
Auf diese Weise können Sie beliebig große Zahlen auf jeder CPU hinzufügen. Alle anderen Berechnungen werden ähnlich durchgeführt, die kleinere CPU benötigt nur mehr Schritte.
Wenn Sie zwei Zahlen mit Bleistift und Papier addieren, arbeiten Sie von rechts nach links, addieren zwei Ziffern, notieren das Ergebnis und tragen jeden Überlauf. Das Addieren großer Zahlen auf einem Computer funktioniert auf die gleiche Weise. Jede Zahl wird durch eine Reihe von "Ziffern" dargestellt, wobei jede "Ziffer" ein Computerwort ist: in Ihren beiden Beispielen 8 oder 32 Bit breit. Wenn zwei solche Zahlen addiert werden, ist es genau der gleiche Vorgang: Addieren Sie zwei "Ziffern", notieren Sie das Ergebnis und tragen Sie jeden Überlauf. Der Unterschied besteht darin, dass jede Ziffer einen Wert zwischen 0 und 2^8 (für einen 8-Bit-Prozessor) oder einen Wert zwischen 0 und 2^32 (für einen 32-Bit-Prozessor) darstellt. Wenn Sie gerne in Zahlenbasen denken, funktioniert die Bleistift-und-Papier-Addition in der Basis 10,
Ignacio Vazquez-Abrams
Jippie