Wie führen Sie Operationen mit großen Zahlen mit einer kleinen ALU mit fester Breite durch?

Ich möchte einen einfachen Taschenrechner entwerfen, wie Sie ihn im Dollar-Shop finden würden. Etwas wie das:

Einfacher Rechner

Dieser kleine Kerl kann eine 8-stellige Zahl anzeigen, was bedeutet, dass 99999999 die größte Zahl ist, die in diesem Format angezeigt werden kann.

Mir ist bekannt, wie eine einfache ALU mit zwei Registern als Eingabe funktioniert.

Wenn ich jetzt ein 32-Bit-Register für Berechnungen verwenden soll, wäre alles in Ordnung, da das Register 99999999 gut aufnehmen kann. Ich möchte jedoch verstehen, wie zwei kleinere Register verwendet werden, um größere Zahlen zu speichern, und wie das mit einer ALU funktioniert?

Möchten Sie, dass es Gleitkommaberechnungen oder nur Festkommazahlen oder nur Ganzzahlen verarbeiten kann?
Langfristig Gleitkommazahl, aber für diese Frage wären nur ganze Zahlen in Ordnung. Ich weiß, dass es mit Dezimalpunkten und Binärzahlen eine endlose Anzahl von Einsen und Nullen gibt, die man haben kann, je nachdem, wie genau man sein möchte. ALUs, die Dezimalzahlen unterstützen, kenne ich noch nicht.
Der allgemeine Begriff für eine Nummer, die größer als Ihre ALU ist, insbesondere eine mit variabler Länge, ist eine "Bignum". Einige Programmiersprachen implementieren dies für Sie.
Es ist wie beim Rechnen mit Bleistift und Papier: Arbeiten Sie an einer Ziffer nach der anderen und behalten Sie den Überblick über die Überträge / Ausleihen.
Ja, genau wie mit Bleistift und Papier. Teilen kann hässlich werden, aber der Rest ist ziemlich einfach. (Sie benötigen natürlich etwas zusätzlichen Speicherplatz, um die Zahlen in voller Größe plus Zwischenergebnisse zu speichern.)

Antworten (2)

Sie können beliebig breite Zahlen mit einer ALU endlicher Breite manipulieren. Jedoch sind mehrere Operationen erforderlich, wenn die Zahl breiter als die ALU ist.

Um dies zu veranschaulichen, verwende ich als Beispiel einen PIC 18. Diese Architektur kann nur 8-Bit-Zahlen direkt manipulieren. Um die 8-Bit-Mengen VAR1 und VAR2 zu addieren und das Ergebnis in SUM einzufügen, würde Code wie folgt benötigt (vorausgesetzt, Banking wird nicht benötigt oder die Bank ist bereits richtig eingerichtet):

         movf var1, w ;var1 in den Akkumulator bringen
         addwf var2, w ; VAR2 hinzufügen
         movwf sum ;Ergebnis speichern

Wenn stattdessen VAR1, VAR2 und SUM 32-Bit-Variablen wären, wäre der Code:

         movf var1+0, w ;Byte 0 machen (niedriges Byte)
         addwf var2+0, w
         movwf Summe+0
         movf var1+1, w ;Byte 1 erstellen
         addwfc var2+1, w
         movwf Summe+1
         movf var1+2, w ;Byte 2 erstellen
         addwfc var2+2, w
         movwf Summe+2
         movf var1+3, w ;Byte 3 erstellen (hohes Byte)
         addwfc var2+3, w
         movwf Summe+3

Jedes Byte wird separat behandelt. Beachten Sie die Verwendung von ADDWFC anstelle von ADDWF für alle außer dem ersten Byte. Diese Anweisung fügt die zwei Bytes hinzu, fügt aber auch den Übertrag aus der vorherigen ALU-Operation hinzu.

Hoffentlich können Sie sehen, dass dieser Ansatz verwendet werden kann, um zwei beliebig große Zahlen zu addieren. Eine breite Arithmetik ist möglich, nur dass es länger dauert und mehrere Durchgänge durch die ALU erfordert, um die gesamte Operation durchzuführen.

Operationen wie AND, OR, XOR usw. sind bitweise unabhängig. Jedes Ausgangsbit kann berechnet werden, wenn nur die entsprechenden Eingangsbits gegeben sind. Solche Operationen werden linear mit der Breite der verarbeiteten Werte skaliert. Die Addition erfordert die beiden Eingangsbits, aber auch das Ergebnis des Übertrags aus dem nächstniedrigeren Bit. Das erfordert, dass ein Zustandsbit zwischen aufeinanderfolgenden Operationen beibehalten wird, skaliert aber immer noch linear mit der Breite der Zahl.

Multiplizieren Sie Skalen mit dem Quadrat der Breite der Zahl, da jeder Teil einer Zahl mit allen Teilen der anderen Zahl multipliziert werden muss. Zwei 32-Bit-Zahlen zu multiplizieren, was bis zu einem 64-Bit-Ergebnis erzeugen kann, dauert viel länger als 8 x 8 auf einer 8-Bit-ALU, aber es ist alles möglich.

Sie würden einen solchen Rechner im Allgemeinen mit einer 4-Bit-ALU (eine BCD-Ziffer) erstellen und alle Berechnungen in BCD Ziffer für Ziffer durchführen, sodass Ihr Speicherregister 8 Ziffern x 4 Bit = 32 Bit insgesamt wäre.

Selbst mit einer niedrigen Taktfrequenz ist das mehr als schnell genug für menschliche Interaktion und minimiert die Hardware.

Zum Addieren fügen Sie einfach eine Ziffer nach der anderen hinzu, von rechts nach links, bis Sie alle 8 gemacht haben (unter Berücksichtigung von Überträgen). Subtraktion ist ähnlich.

Multiplikation und Division sind im Grunde wiederholte Additionen oder Subtraktionen und können auf ähnliche Weise durchgeführt werden (Sie müssen möglicherweise 9 * 9 * 8-mal mit einer 4-Bit-ALU addieren, um eine 8-stellige x 8-stellige Multiplikation durchzuführen - im schlimmsten Fall - beispielsweise 99999999 * 1 .

Das Ergebnis, das in BCD vorliegt, kann fast direkt an die LCD-Anzeige gesendet werden (7-Segment-Codierung und möglicherweise trotz Triplex-LCD-Ansteuerung).

Natürlich können Sie so etwas heutzutage einfacher machen, indem Sie eine 32-Bit-ALU verwenden und Code mit Assembler-Handcodierung der Mathematik, Doubles in C usw. schreiben, aber so funktionieren die billigen Taschenrechner nicht.