Wie ermittelt ein Computer den Datentyp eines Bytes?


31

Wenn der Computer beispielsweise 10111100ein bestimmtes Byte RAM gespeichert hat , wie kann der Computer dieses Byte als Ganzzahl, ASCII-Zeichen oder etwas anderes interpretieren? Werden Typdaten in einem benachbarten Byte gespeichert? (Ich glaube nicht, dass dies der Fall wäre, da dies die doppelte Menge an Speicherplatz für ein Byte zur Folge hätte.)

Ich vermute, dass ein Computer möglicherweise nicht einmal die Art der Daten kennt, sondern nur das Programm, das sie verwendet. Ich vermute, da RAM R AM ist und daher nicht sequentiell gelesen wird, weist ein bestimmtes Programm die CPU lediglich an, die Informationen von einer bestimmten Adresse abzurufen, und das Programm definiert, wie es behandelt werden soll. Dies scheint mit der Programmierung von Dingen wie der Notwendigkeit von Typecasting zusammen zu passen.

Bin ich auf dem richtigen Weg?


4
Als Randnotiz: Wenn Sie über Typen sprechen, müssen Sie dies in einem Sprachkontext tun. Es bleibt dem Compiler überlassen, mit solchen Dingen umzugehen (Symbole, Prüftypen, Operationen, Casting, Adress-RAM usw.). Nur CPU und RAM kennt Bytes
jean

4
Der Datentyp eines Bytes ist ein Byte. Darüber hinaus weiß der Computer nichts. Ein Programm könnte ein Byte oder eine Gruppe von Bytes als einen bestimmten Datentyp interpretieren und versuchen, Operationen an diesen auszuführen, aber es gibt dort keine Einschränkungen. Dieselbe Gruppe von Bytes kann als mehr als ein Datentyp interpretiert werden (dh das Umsetzen von Zeigern auf Werttypen, C-ähnliche Vereinigungen usw.). Dass RAM nicht sequentiell gelesen wird, ist nicht wirklich relevant. - Es ist mehr, weil RAM Allzweck ist. - Register werden beispielsweise auch nicht sequentiell gelesen, sondern typisiert.
BrainSlugs83

5
Schamloser Stecker für mich, aber diese Frage wurde den Programmierern SE vor ungefähr einem Monat gestellt. Hier ist meine Antwort darauf . Zu diesem Zeitpunkt ist es etwas lang, greift es jedoch aus verschiedenen Blickwinkeln an.
Shaz,

2
Eine nützliche Folge der Tatsache, dass die Hardware datentypunabhängig ist, besteht darin, dass ein einzelnes Byte (oder Wort usw.) von einem Programm auf mehrere Arten interpretiert werden kann. Insbesondere wird das vorübergehende Interpretieren einer Gleitkommazahl als Ganzzahl verwendet, um die schnelle Quadratwurzel zu berechnen .
Aoeuid

@ BrainSlugs83, könntest du darüber nachdenken, das in eine Antwort umzuwandeln?
DW

Antworten:


38

Your suspicion is correct. The CPU doesn't care about the semantics of your data. Sometimes, though, it does make a difference. For example, some arithmetic operations produce different results when the arguments are semantically signed or unsigned. In that case you need to tell the CPU which interpretation you intended.

It is up to the programmer to make sense of her data. The CPU only obeys orders, blissfully unaware of their meaning or goals.


1
Regarding "when the arguments are semantically signed or unsigned", how would the CPU know? The CPU operations just see parameter bytes and lack that sort of data type context awareness. You imply the data type by choosing the appropriate CPU operation (or your compiler does).
Shiv

4
@Shiv In such cases, the CPU is actually issued a different instruction to process signed numbers versus unsigned numbers. As in the OP's suspicions, the program is obliged to provide those details, because the CPU is unaware.
Cort Ammon - Reinstate Monica

2
I've been working with computers as long as I remember myself, and even though I know that CPU doesn't care about the high level constructs we use on high level programming, but this separation of concepts still freaks me out from time to time
Loupax

1
@Loupax Well, working with a really low-level assembly helps quite a bit - even mov al, 42 is kind of high-level - it's obvious there's only one possible instruction this could call, but it's still somewhat abstracted away. However, using mov.8 al, 42 explicitly makes this painfully obvious :)
Luaan

1
@Shiv: I'd like to note that there are machines where the data in memory are typed. These are called tagged memory architectures (or simply tagged architectures) but they've not been as successful commercially as regular architectures partly because we now program mostly in compiled languages instead of assembly and the compiler takes care of typing. See: en.wikipedia.org/wiki/Tagged_architecture
slebetman

14

As others have already answered, today's common CPUs do not know what a given memory position contains; the software decides.

However, there are other possibilities. Lisp Machines for example used a tagged architecture which stored the type of each memory position; that way the hardware itself could do some of the work of high-level languages.

And even now, I guess you could consider the NX bit in Intel, AMD, ARM and other architectures to follow the same principle: distinguish at the hardware level whether a given memory zone contains data or instructions.

Also, just for completeness, in Harvard architectures (like some microcontrollers) data and instructions are physically separated, so the CPU does have some idea of what it is reading.

In this Quora question there's some commentary on how the tagged memory worked, its performance implications and demise, and more.


Tagged architecture is an interesting note. Would it be significantly faster?
Bassinator

4

Yes. The program just gets a byte from the memory and it can interpret it however it wants.


3

There are no type annotations.
RAM stores pure data, and then program defines what to do.

With CPU registers is a bit harder, if you have registers of given type (like FPU), you tell what is inside.
Operations on floating point registers are explicitly using typed data. You or your compiler tell what and when should be put there, so you not have such freedom.
Computer does not make any assumptions on underlying data in RAM, and in registers with one exception - typed registers in CPU are of known type, optimised to deal with it. This is only to show that there are places where data is to be of expected type, but nothing stops you from casting strings to floats and multiply them.

In programming languages you specify type, or in higher level languages data is general and compiler / interpreter / VM encodes what is inside with overhead.
For example in C your pointer type tells what to do with data, how to access it.

Of course you can read string (characters) and treat then as floating point values, integers and mix them.


Even bits in an FPU register don't always represent floating point values. In the old days (maybe not so much anymore?), a common optimization was to use floating point registers (64-bits or larger) to copy data faster than general purpose/integer registers (32-bit), being twice as big, they were generally able to copy data twice as fast.
Seth

1
I totally agree with you, that is why I wrote somebody might push strings there. And in the same times people did floating point operations on integers, because it was faster. That is the point!
Evil

@HCBPshenanigans there are instructions that manipulate floating-point values. If FADD is used it only makes sense that the (4,8,or 10)-byte groups of memory held floating-point numbers. That's true for several kinds of instruction: multiply two integers only makes sense if they are integers, jump only makes sense if it's an address.
JDługosz

@seth and evilJS that's not assumed to be the case for legacy floating point stacked 8087 instructions, but is the case for newer CIMD registers which may be used just for loading/saving with no interpretation (though they must be aligned), and a caveat that if the CIMD registers were never used than they don't need to be saved in a context switch. If you (only) move 8 bytes via XMM register it's a net loss as the whole set needs to be saved.
JDługosz

3

The CPU doesn't care, it executes assembly code, which justs merely moves data around, shift it, add it or multiply it...

Data Types are a higher level language concept: in C or C++ you need to specify Types for every single piece of data you manipulate; the C/C++ Compiler takes care of transforming these pieces of data into the right commands for the CPU to process (compilers write assembly code)

In some even higher level languages, Types may be inferred: in Python or Javascript, for example, one does not have to specify data types, yet data has a type and you can't add a string with an integer, but you can add a float with an integer: the 'compiler' (which in the case of Javascript is a JIT (Just in Time) Compiler. Javascript is often called an 'interpreted' language because historically browsers interpreted Javascript code, but nowadays Javascript engines are compilers.

Code, always ends up being compiled to machine code, but obviously machine code format depends on the machine you're targeting (x86 64bit code won't work on a x86 32 bits machine or a ARM processor for example)

So there is actually a lot of layers involved in running interpreted code.

Java and C# are other interesting ones, as Java or C# code is technically 'compiled' to a Java binary (bytecode), but that code itself is then interpreted by the Java Runtime, which is specific to the underlying hardware (one needs to install the JRE targeting the right machine to run Java binaries (Jars) )


A compiler compiles, be it JIT or not; and an interpreter interprets without compiling (because if not it would be a compiler!). They are very different things. And regarding "Java being funny" because of bytecode interpretation, consider that even x86 machine code will actually be interpreted (or even compiled?) by the very microprocessor into microcode.
hmijail

Thanks for the clarification... Agreed: a compiler compiles, and an interpreter interprets. In the case of Javascript though the story is a bit complicated since some older browser interpret the code, while more modern browsers actually compile just-in-time, which is probably why it is still referred to as an 'interpreted' language even though it is technically not anymore.
MrE

But AFAIK, JS starts interpreted, and then might get compiled as needed. And JITs can switch from interpreted to compiled to interpreted again, depending on lots of things. For example, a piece of code might get compiled for a variable having a given type; but then the code is run again with that variable having a different type, so the existing compiled code can't be used so the interpreter jumps in - until the code gets compiled again for the new type...
hmijail

You're citing me on something I didn't say, please remove it because it's totally wrong. Microcode has NOTHING to do with the OS; it's something internal to the microprocessor. 32 bit or 64 bit also has nothing to do with it.
hmijail

3

Datatypes are not a hardware feature. The CPU knows a couple (well, a lot) of different commands. Those are called the instruction set of a CPU.

One of the best known ones is the x86 instruction set. If you search for "multiply" on this page, you get 50 results. MULPD and MULSD for the multiplication of doubles, FIMUL for integer multiplication, ...

Those commands work on registers. Registers are memory slots which can contain a fixed number of bits (often 32 or 64, depending on which architecture your CPU uses), no matter what these bits represent. Hence the CPU instruction interprets the values of the registers in a different way, but the values themselves don't have types.

An example was given at PyCon 2017 by Stuart Williams:

enter image description here


1
Beachten Sie, dass dies nicht strikt zutrifft: Es gibt Sonderregister, die keine willkürlichen Werte enthalten können (z. B. Zeigerregister, die keine Adressen sind und keine willkürlichen Zusätze zulassen, oder Gleitkommaregister, wo dies möglich ist nicht normalisierte Werte nicht speichern). Ihre Antwort ist jedoch für Allzweckregister auf den meisten Architekturen richtig .
Gilles 'SO - hör auf böse zu sein'

2

...that a particular program just tells the CPU to fetch the info from a specific address and the program defines how to treat it.

Exactly. But RAM is not read "sequentially", and it stands for Random Access Memory which is exactly the opposite.

Neben dem Wissen, was ein Byte ist , wissen Sie nicht einmal, ob es sich um ein Byte oder ein Fragment eines größeren Elements wie einer Gleitkommazahl handelt.

Ich möchte andere Antworten mit einigen konkreten Beispielen ergänzen.

Überlegen Sie 01000001. Das Programm kopiert es möglicherweise als Teil eines großen Datenpakets von einem Ort an einen anderen, ohne Rücksicht auf seine Bedeutung. Wenn Sie dies jedoch an die vom Videopuffer im Textmodus verwendete Adresse kopieren, wird der Buchstabe Aan einer bestimmten Position auf dem Bildschirm angezeigt. Die exakt gleiche Aktion, wenn sich die Karte in einem CGA-Grafikmodus befindet, zeigt ein rotes Pixel und ein blaues Pixel an.

In einem Register könnte es sich bei der Zahl 65 um eine Ganzzahl handeln. Rechnen, um das 32er-Bit zu setzen, kann alles bedeuten ohne Kontext , es kann jedoch insbesondere sein, dass ein Buchstabe in Kleinbuchstaben geändert wird.

Die 8086-CPU verfügt (noch) über spezielle Anweisungen namens DAA , die verwendet werden, wenn das Register zwei Dezimalstellen enthält. Wenn Sie diese Anweisung also nur verwendet haben, interpretieren Sie sie als zwei Stellen 41.

Programme stürzen ab, weil ein Speicherwort gelesen wird und denkt, es sei ein Zeiger, wenn etwas anderes dort gespeichert wurde.

Verwenden eines Debuggers, Überprüfen des Speichers, einer Karte verwendet, um die Interpretation für die Anzeige zu steuern. Ohne diese Symbolinformationen können Sie in einem Low-Level-Debugger Folgendes angeben: Diese Adresse als 16-Bit-Wörter anzeigen, diese Adresse als langen Gleitkommawert als Zeichenfolgen anzeigen ... wie auch immer. Bei einem Netzwerk-Packet-Dump oder einem unbekannten Dateiformat ist es eine Herausforderung, das Rätsel zu lösen.

Dies ist eine wichtige Quelle für Leistung und Flexibilität in der modernen Computerarchitektur: Eine Speicherzelle kann alles , Daten oder Befehle, bedeuten , die nur implizieren, was sie für das Programm bedeutet, was sie mit dem Wert tut und wie sich dies auf nachfolgende Operationen auswirkt. bedeutung ist tiefer als ganzzahlige breite: sind diese zeichen ... zeichen in ascii oder ebcdic? Bilden Sie Wörter in Englisch oder SQU-Produktcodes? Die zu sendende Adresse oder die Absenderadresse? Die Interpretation der untersten Ebene (logische Bits; ganzzahlig, vorzeichenbehaftet oder vorzeichenlos; float; bcd; pointer) ist auf Befehlssatzebene kontextbezogen, aber Sie sehen, dass auf einer bestimmten Ebene alles Kontext ist: das to Adresse aufgrund der Position auf dem Umschlag so ist, wie sie ist. Es steht im Zusammenhang mit den Regeln des Postboten, nicht der CPU. Der Kontext ist ein großes Kontinuum, an dessen einem Ende sich Teile befinden.


※ Footnote: The DAA instruction is encoded as a byte 00100111. So that byte is the aforenamed instruction if read in the instruction stream, and the digits 27 if interpreted as bcd digits, and 0x27 = 39 as an integer, which is the numeral 9 in ASCII, and part of the interrupt table (half of INT 13 2-byte address, used for BIOS service routines).


1

The only way the computer knows that a memory location is an instruction is that a special-purpose register called the instruction pointer points to them at one point or another. If the instruction pointer points to a memory word, it is loaded as an instruction. Other than that, the computer has no way of knowing the difference between programs and other types of data.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.