例如,如果计算机已10111100
存储在RAM的特定字节中,计算机如何知道将此字节解释为整数,ASCII字符或其他内容?类型数据是否存储在相邻字节中?(我认为情况并非如此,因为这将导致一个字节使用两倍的空间。)
我怀疑也许计算机甚至不知道数据类型,只有使用它的程序才知道。我的猜测是,由于RAM是R AM,因此不能按顺序读取,因此某个特定程序只是告诉CPU从特定地址获取信息,而该程序定义了如何处理它。这似乎适合编程,例如需要类型转换。
我在正确的轨道上吗?
例如,如果计算机已10111100
存储在RAM的特定字节中,计算机如何知道将此字节解释为整数,ASCII字符或其他内容?类型数据是否存储在相邻字节中?(我认为情况并非如此,因为这将导致一个字节使用两倍的空间。)
我怀疑也许计算机甚至不知道数据类型,只有使用它的程序才知道。我的猜测是,由于RAM是R AM,因此不能按顺序读取,因此某个特定程序只是告诉CPU从特定地址获取信息,而该程序定义了如何处理它。这似乎适合编程,例如需要类型转换。
我在正确的轨道上吗?
Answers:
您的怀疑是正确的。CPU不在乎数据的语义。但是,有时确实会有所作为。例如,当参数被语义签名或未签名时,某些算术运算会产生不同的结果。在这种情况下,您需要告诉CPU您打算使用哪种解释。
程序员应了解自己的数据。CPU仅服从命令,而没有意识到命令的含义或目标。
mov al, 42
是高级的-显然只有一个可能的指令可以调用,但是它仍然有些抽象。但是,mov.8 al, 42
显式使用使这一点变得很痛苦:)
正如其他人已经回答的那样,当今的通用CPU不知道给定的内存位置包含什么。软件决定。
但是,还有其他可能性。例如,Lisp Machines使用标记的体系结构来存储每个存储位置的类型。这样,硬件本身就可以完成一些高级语言的工作。
甚至现在,我猜您仍可以考虑将Intel,AMD,ARM和其他体系结构中的NX位遵循相同的原理:在硬件级别区分给定的存储区是否包含数据或指令。
同样,仅出于完整性考虑,在哈佛体系结构(如某些微控制器)中,数据和指令在物理上是分开的,因此CPU确实对正在读取的内容有所了解。
在这个Quora问题中,有一些关于标记的内存如何工作,其性能影响和消亡等方面的评论。
没有类型注释。
RAM存储纯数据,然后程序定义要做什么。
使用CPU寄存器要困难一些,如果您具有给定类型的寄存器(例如FPU),则可以告诉其中的内容。
浮点寄存器上的操作明确地使用类型化数据。您或您的编译器会告诉您应在何时何地放置什么内容,因此您没有这种自由。
计算机对RAM中的基础数据不做任何假设,在寄存器中也没有任何例外-一个例外-CPU中的类型寄存器是已知类型的,可以对其进行优化。这只是为了表明在某些地方数据是预期类型的,但是没有什么可以阻止您将字符串转换为浮点数并将它们相乘。
在编程语言中,您可以指定类型,在高级语言中,数据是通用的,而编译器/解释器/ VM会对内部内容进行编码,而会产生额外的开销。
例如,在C语言中,您的指针类型告诉您如何处理数据,如何访问数据。
当然,您可以读取字符串(字符),然后将其视为浮点值,整数并将其混合。
CPU不在乎,它执行汇编代码,该代码只是移动数据,对其进行移位,相加或相乘...
数据类型是一种高级语言概念:在C或C ++中,您需要为要处理的每条数据指定类型。C / C ++编译器负责将这些数据片段转换为供CPU处理的正确命令(编译器编写汇编代码)
在某些甚至更高级别的语言中,可以推断出类型:例如,在Python或Javascript中,不必指定数据类型,但是数据具有类型,您不能添加带有整数的字符串,但是可以添加一个带有整数的浮点数:“编译器”(对于Javascript,它是JIT(Just in Time)编译器。Javascript通常称为“解释性”语言,因为历史上浏览器会解释Javascript代码,但如今Javascript引擎是编译器。
代码总是最终会被编译成机器代码,但是显然机器代码格式取决于您所针对的机器(例如,x86 64位代码在x86 32位机器或ARM处理器上无法使用)
因此,实际上,运行解释代码涉及很多层。
Java和C#是其他有趣的代码,因为Java或C#代码在技术上被“编译”为Java二进制(字节码),但是该代码本身随后由Java运行时解释,该运行时特定于基础硬件(需要安装一个针对正确的机器以运行Java二进制文件(JAR)的JRE)
数据类型不是硬件功能。CPU知道几个(很多)不同的命令。这些被称为CPU 的指令集。
x86指令集是最著名的指令集之一。如果在此页面上搜索“乘”,您将获得50个结果。MULPD
和MULSD
双打的乘法,
FIMUL
整数乘法,...
这些命令在寄存器上起作用。寄存器是内存插槽,无论这些位代表什么,它们都可以包含固定数量的位(通常为32或64,具体取决于CPU使用的体系结构)。因此,CPU指令以不同的方式解释寄存器的值,但是值本身没有类型。
Stuart Williams在PyCon 2017上给出了一个示例:
...一个特定的程序只是告诉CPU从一个特定的地址中获取信息,然后该程序定义了如何处理它。
究竟。但是RAM不会“顺序”读取,它代表随机存取存储器,而正好相反。
除了知道字节是什么之外,您甚至都不知道它是字节还是更大项目(例如浮点数)的片段。
我想通过举一些具体的例子来补充其他答案。
考虑一下01000001
。该程序可能会将其作为大量数据的一部分从一个位置复制到另一位置,而不考虑其含义。但是将其复制到文本模式视频缓冲区使用的地址将导致该字母A
显示在屏幕上的某些位置。当卡处于CGA图形模式时,完全相同的操作将显示红色像素和蓝色像素。
在寄存器中,它可以是65的整数。进行算术运算以设置32位可能意味着没有上下文的任何含义,但可能具体是将字母更改为小写。
8086 CPU(仍)具有称为DAA ※的特殊指令,该指令在寄存器包含两位十进制数字时使用,因此,如果您仅使用该指令,则会将其解释为两位数字41
。
程序崩溃是因为读取了一个存储字,认为它是一个指针,而在其他地方存储了一个东西。
使用调试器检查内存,使用映射来指导显示解释。没有此符号信息,低级调试器就可以指定:以16位字显示此地址,以长浮点数,字符串等形式显示此地址。查看网络数据包转储或未知文件格式,将其弄乱是一个挑战。
这是现代计算机体系结构中强大功能和灵活性的主要来源:存储单元可以表示任何内容,数据或指令,这些内容,内容或指令仅隐含在它对程序“意味着”的意义上,即它对值的作用以及对后续操作的影响。 含义比整数宽度还要深:这些字符是... ASCII还是ebcdic字符?用英语或SQU产品代码形成单词?要发送到的地址或它来自的回信地址?最低级别的解释(逻辑位;类似于整数,符号或无符号;浮动; BCD;指针)是在指令集层次情境,但是你看,它的所有在一定程度方面:在以地址是因为它在信封上打印的位置。它与邮递员的规则有关,而不与CPU有关。上下文是一个很大的连续体,一端是位。
※脚注:DAA指令编码为字节00100111
。因此,如果在指令流中读取了该字节,则该字节为前一条指令;如果将其27
解释为bcd数字,则该数字为零,并且0x27 = 39为整数(以ASCII 表示的数字9)以及中断表的一部分(INT 13的一半) 2字节地址,用于BIOS服务程序。