Wie würde die ALU in einem Mikroprozessor zwischen einer mit Vorzeichen versehenen Zahl -7, die mit 1111 bezeichnet ist, und einer mit Vorzeichen versehenen Zahl 15, die ebenfalls mit 1111 bezeichnet ist, unterscheiden?
Wie würde die ALU in einem Mikroprozessor zwischen einer mit Vorzeichen versehenen Zahl -7, die mit 1111 bezeichnet ist, und einer mit Vorzeichen versehenen Zahl 15, die ebenfalls mit 1111 bezeichnet ist, unterscheiden?
Antworten:
Die kurze und einfache Antwort lautet: Nein. Keine moderne Hauptprozessor-ISA funktioniert so, wie Sie denken.
Für die CPU ist es nur ein kleines Muster. Es liegt an Ihnen, dem Programmierer, den Überblick zu behalten, was dieses Bitmuster bedeutet.
Im Allgemeinen unterscheiden ISAs beim Speichern nicht zwischen verschiedenen Datentypen. (Ignorieren von Spezialregistern wie z. B. Floating-Registern in einer FPU.) Es ist nur ein bedeutungsloses Bitmuster für die CPU. ISAs verfügen jedoch über verschiedene Arten von Anweisungen, die das Bitmuster auf unterschiedliche Weise interpretieren können. Beispielsweise arithmetische Befehle wie MUL
, DIV
, ADD
, SUB
interpretiert das Bitmuster als eine Art - Nummer, während logische Befehle wie AND
, OR
, XOR
interpretiert sie als ein Array von booleans. Es ist also Aufgabe des Programmierers (oder des Autors des Interpreters oder Compilers, wenn Sie eine höhere Sprache verwenden), die richtigen Anweisungen auszuwählen.
Beispielsweise kann es durchaus separate Anweisungen für vorzeichenbehaftete und nicht vorzeichenbehaftete Nummern geben. Einige ISAs enthalten auch Anweisungen für die Arithmetik mit binär codierten Dezimalstellen.
Beachten Sie jedoch, dass ich oben "Modern Mainstream ISA" geschrieben habe. Es gibt in der Tat nicht-Mainstream- oder historische ISAs, die anders funktionieren. Beispielsweise unterscheiden sowohl die ursprüngliche 48-Bit-CISC-ISA des IBM AS / 400 als auch die aktuelle POWER-basierte 64-Bit-RISC-ISA des Systems, das jetzt IBM i heißt, zwischen Zeigern und anderen Werten. Zeiger sind immer mit Tags versehen und enthalten Typinformationen und Rechteverwaltung. Die CPU weiß, ob ein Wert ein Zeiger ist oder nicht, und nur der privilegierte i / OS-Kernel darf Zeiger frei manipulieren. Benutzeranwendungen können Zeiger, die sie besitzen, nur mithilfe einer kleinen Anzahl sicherer Anweisungen so bearbeiten, dass sie auf den Speicher verweisen, den sie besitzen.
Es gab auch einige historische ISA-Entwürfe, die zumindest eine begrenzte Form der Typenerkennung beinhalteten.
char
, das ist ein 16-Bit - Typ ohne Vorzeichen. Natürlich gibt es in Java-Bytecode noch keine vorzeichenlosen arithmetischen Anweisungen, da alle char
Werte int
für die Arithmetik automatisch auf (32-Bit- Vorzeichen ) hochgestuft werden.
Kurzfassung: Es weiß nicht. Man kann es nicht sagen.
Wenn 1111
für -7 steht, haben Sie eine Darstellung der Vorzeichengröße, bei der das erste Bit das Vorzeichen und der Rest der Bits die Größe ist. In diesem Fall ist die Arithmetik etwas kompliziert, da ein vorzeichenloses Add und ein vorzeichenbehaftetes Add unterschiedliche Logik verwenden. Sie hätten also wahrscheinlich einen SADD
und einen UADD
Opcode, und wenn Sie den falschen auswählen, erhalten Sie unsinnige Ergebnisse.
In 1111
der sogenannten Zweierkomplement-Repräsentation steht sie jedoch häufiger für -1 . In diesem Fall ist es der ALU einfach egal, ob die Nummern signiert oder nicht signiert sind! Nehmen wir zum Beispiel die Operation von 1110 + 0001
. In der vorzeichenbehafteten Arithmetik bedeutet dies "-2 + 1" und das Ergebnis sollte -1 ( 1111
) sein. In vorzeichenloser Arithmetik bedeutet dies "14 + 1" und das Ergebnis sollte 15 ( 1111
) sein. Die ALU weiß also nicht, ob Sie ein signiertes oder ein nicht signiertes Ergebnis wünschen, und es ist ihr egal. Die Addition wird so ausgeführt, als wäre sie nicht signiert, und wenn Sie sie anschließend als vorzeichenbehaftete Ganzzahl behandeln möchten, liegt dies bei Ihnen.
EDIT: Wie Ruslan und Daniel Schepler in den Kommentaren zutreffend hervorheben, benötigen einige Operanden auch auf einem Zwei-Komponenten-Rechner noch getrennte Versionen mit und ohne Vorzeichen. Addition, Subtraktion, Multiplikation, Gleichheit usw. funktionieren einwandfrei, ohne zu wissen, ob die Zahlen signiert sind oder nicht. Divisions- und Über- / Unter-Vergleiche müssen jedoch separate Versionen haben.
BEARBEITEN BEARBEITEN : Es gibt auch einige andere Darstellungen, wie die eigene Ergänzung , aber diese werden im Grunde genommen nie mehr verwendet, sodass Sie sich keine Sorgen mehr machen sollten.
<
<=
>=
>
sind für vs. unsigned Operanden unterzeichnet , während ==
und !=
sind Signedness unabhängig.
Einer der großen Vorteile der Zweierkomplement-Mathematik, die in allen modernen Architekturen verwendet wird, besteht darin, dass die Additions- und Subtraktionsanweisungen für vorzeichenbehaftete und vorzeichenlose Operanden genau gleich sind.
Viele CPUs haben nicht einmal Multiplikations-, Divisions- oder Modulusbefehle. Wenn dies der Fall ist, müssen die Anweisungen in getrennten, signierten und nicht signierten Formen vorliegen, und der Compiler (oder der Assembler-Programmierer) wählt die entsprechende aus.
CPUs haben im Allgemeinen auch unterschiedliche Anweisungen für vorzeichenbehaftete oder vorzeichenlose Vergleiche. Beispielsweise könnte x86 einem CMP
mit JL
(Jump if Less than) folgen, wenn der Vergleich signiert werden soll, oder JB
(Jump if Below), wenn der Vergleich nicht signiert werden soll. Auch hier würde der Compiler oder der Programmierer die richtige Anweisung für den Datentyp auswählen.
Einige andere Anweisungen kommen häufig in vorzeichenbehafteten und vorzeichenlosen Varianten vor, z. B. das Verschieben nach rechts oder das Laden eines Werts in ein breiteres Register mit oder ohne Vorzeichenerweiterung.
smulh
und umulh
die nur die oberen Bits der Multiplikation und vorzeichenbehaftete und vorzeichenlose Befehle zurückgeben Liefert das Ergebnis in einem Register, das doppelt so breit ist wie die Quelloperanden.
Das tut es nicht. Der Prozessor verwendet den Befehlssatz, um anzugeben, welche Art von Daten er betrachtet und wohin sie gesendet werden sollen. Im Operanden selbst gibt es nichts über Einsen und Nullen, was der ALU von Natur aus signalisieren könnte, ob es sich bei den Daten um Zeichen, Float, Int, Int mit Vorzeichen usw. handelt als 2s-Ergänzung zu interpretieren.
char
Hardware-Ebene gibt es so etwas wie kein . Vielleicht war es einmal in der Zeit der mechanischen Ferndrucker. Aber heute, eine char
ist nur eine Zahl, soweit die Hardware betrifft. Der Grund, warum unterschiedliche Zahlen unterschiedlichen Buchstabenformen auf Ihrem Bildschirm entsprechen, ist, dass diese Zahlen verwendet werden, um unterschiedliche Bitmaps oder verschiedene Zeichenroutinen aus einer großen Tabelle (dh aus einer "Schriftart") auszuwählen.
Zu den bereits gemachten Antworten möchte ich noch etwas hinzufügen:
In den meisten anderen Antworten wird darauf hingewiesen, dass in der Zweierkomplementarithmetik das Ergebnis für vorzeichenbehaftete und vorzeichenlose Zahlen dasselbe ist:
-2 + 1 = -1 1110 + 0001 = 1111
14 + 1 = 15 1110 + 0001 = 1111
Es gibt jedoch Ausnahmen:
Division:
-2 / 2 = -1 1110 / 0010 = 1111
14 / 2 = 7 1110 / 0010 = 0111
Comparison:
-2 < 2 = TRUE 1110 < 0010 = TRUE
14 < 2 = FALSE 1110 < 0010 = FALSE
"Typical" (*) multiplication:
-2 * 2 = -4 1110 * 0010 = 11111100
14 * 2 = 28 1110 * 0010 = 00011100
(*) Bei vielen CPUs ist das Ergebnis einer Multiplikation von zwei n-Bit-Zahlen (2 * n) Bits breit.
Für solche Operationen haben die CPUs unterschiedliche Anweisungen für vorzeichenbehaftete und vorzeichenlose Arithmetik.
Dies bedeutet, dass der Programmierer (oder der Compiler) andere Anweisungen für vorzeichenbehaftete und vorzeichenlose Arithmetik verwenden muss.
Die x86-CPU hat zum Beispiel einen Befehl, der div
für das Ausführen einer vorzeichenlosen Division und einen Befehl, der idiv
für das Ausführen einer vorzeichenbehafteten Division benannt ist.
Es gibt auch verschiedene "bedingte" Anweisungen (bedingte Sprünge, Bit-Ein-Bedingung setzen) sowie Multiplikationsanweisungen für vorzeichenbehaftete und vorzeichenlose Arithmetik.