Grundsätzlich ist jeder moderne Computer eine Bit-Push-Maschine. Normalerweise werden Bits in Datenclustern verschoben, die als Bytes, Wörter, Dwords oder Qwords bezeichnet werden.
Ein Byte besteht aus 8 Bits, einem Wort 2 Bytes (oder 16 Bits), einem Wort 2 (oder 32 Bits) und einem Wort 2 (oder 64 Bits). Dies ist nicht die einzige Möglichkeit, Bits anzuordnen. 128-Bit- und 256-Bit-Manipulationen treten häufig auch bei SIMD-Befehlen auf.
Montageanweisungen arbeiten mit Registern und Speicheradressen arbeiten normalerweise in einer der obigen Formen.
ALU (Arithmetic Logic Units) verarbeiten solche Bitbündel, als ob sie Ganzzahlen darstellen (normalerweise Two's Complement Format), und FPUs, als ob sie Gleitkommawerte darstellen (normalerweise IEEE 754-style float
und double
). Andere Teile verhalten sich so, als wären sie gebündelte Daten eines Formats, von Zeichen, Tabelleneinträgen, CPU-Anweisungen oder Adressen.
Auf einem typischen 64-Bit-Computer sind Bündel von 8 Bytes (64 Bit) Adressen. Wir zeigen diese Adressen konventionell als Hex-Format (wie 0xabcd1234cdef5678
) an, aber das ist nur eine einfache Möglichkeit für Menschen, die Bitmuster zu lesen. Jedes Byte (8 Bit) wird als zwei Hexadezimalzeichen geschrieben (entsprechend stellt jedes Hexadezimalzeichen - 0 bis F - 4 Bit dar).
Was tatsächlich vor sich geht (für ein gewisses Maß an tatsächlichem) ist, dass es Bits gibt, die normalerweise in einem Register oder an benachbarten Orten in einer Speicherbank gespeichert sind, und wir versuchen nur, sie einem anderen Menschen zu beschreiben.
Das Folgen eines Zeigers besteht darin, den Speichercontroller aufzufordern, uns einige Daten an diesem Ort zu geben. Normalerweise fragt man den Speichercontroller nach einer bestimmten Anzahl von Bytes an einem bestimmten Ort (na ja, implizit einem Bereich von Orten, normalerweise zusammenhängend), und er wird über verschiedene Mechanismen bereitgestellt, auf die ich nicht eingehen werde.
Der Code gibt normalerweise ein Ziel für die abzurufenden Daten an - ein Register, eine andere Speicheradresse usw. - und normalerweise ist es eine schlechte Idee, Gleitkommadaten in ein Register zu laden, das eine Ganzzahl erwartet, oder umgekehrt.
Der Typ der Daten in C / C ++ wird vom Compiler verfolgt und ändert, welcher Code generiert wird. Normalerweise enthalten die Daten nichts Eigenes, was sie tatsächlich zu einem bestimmten Typ macht. Nur eine Sammlung von Bits (in Bytes angeordnet), die vom Code ganzzahlig (oder floatartig oder adressenartig) manipuliert werden.
Hiervon gibt es Ausnahmen. Es gibt Architekturen , bei denen bestimmte Dinge eine andere sind Art von Bits. Das gebräuchlichste Beispiel sind geschützte Ausführungsseiten - während Anweisungen, die der CPU mitteilen, was zu tun ist, Bits sind, können zur Laufzeit die (Speicher-) Seiten, die auszuführenden Code enthalten, nicht geändert werden, und Sie können keine Seiten ausführen, die nicht markiert sind als Ausführungsseiten.
Es gibt auch Nur-Lese-Daten (manchmal im ROM gespeichert, in die physisch nicht geschrieben werden kann!), Ausrichtungsprobleme (einige Prozessoren können keine double
s aus dem Speicher laden, wenn sie nicht auf bestimmte Weise ausgerichtet sind, oder SIMD-Anweisungen, die eine bestimmte Ausrichtung erfordern) und Unmengen von andere architektonische Macken.
Sogar die obige Detailebene ist eine Lüge. Computer bewegen sich nicht "wirklich" um Bits, sondern um Spannungen und Ströme. Diese Spannungen und Ströme erfüllen manchmal nicht das, was sie auf der Abstraktionsebene von Bits "tun" sollen. Die Chips sollen die meisten dieser Fehler erkennen und korrigieren, ohne dass die übergeordnete Abstraktion sich dessen bewusst sein muss.
Auch das ist eine Lüge.
Jede Abstraktionsebene verbirgt die folgende und lässt Sie über das Lösen von Problemen nachdenken, ohne Feynman-Diagramme berücksichtigen zu müssen, um sie auszudrucken "Hello World"
.
Bei einem ausreichenden Maß an Ehrlichkeit drücken Computer Bits, und diese Bits haben eine Bedeutung in der Art und Weise, wie sie verwendet werden.