为什么一个字大于1个字节?

时间:2012-07-16 21:08:25

标签: c++ memory assembly cpu cpu-registers

如果变量是booleanchar(在C / C ++中)或byte(在某些语言中如Java - 不等待VM上的Java)和CPU使用大于1字节的字,是不是浪费了空间?我听说当变量存储在存储器中时它可以存储得更紧凑,例如1字节,即使一个字是4字节。有谁可以解释这是怎么发生的?这似乎是倒退,因为寄存器比RAM更有价值。

7 个答案:

答案 0 :(得分:8)

尽管存储号码能够存储数字,但寄存器并不完全是“空间”。

考虑这个例子:你在一个大盒子里有一堆名片,你想按字母顺序排列它们。在这样做的过程中,您将盒子中的卡片从一个地方移动到另一个地方。虽然当您将卡片移到盒子中的新位置时手中拿着一张卡片,但是您的手不能像盒子一样为卡片提供存储空间。你手中的地方太贵了,不能称之为“空间”。

继续使用卡片类比,假设卡片有不同的尺寸。您的手的大小可以让您一次握住一张大卡,两张中卡或四张小卡。但是,当您对卡片进行分类时,获取多张卡片的能力对您来说很少有利,特别是当卡片统一洗牌时:多张卡片有多个目标位置,因此如果您抓住,则需要执行更复杂或不必要的操作多张牌同时出现。

类似地,CPU的寄存器可能包含多个字节,但是如果需要执行计算,通常无法告诉CPU使用哪个字节:寄存器作为不可分割的单元参与操作。这就是为什么整个字用于寄存器中的数据,即使只有一个字节就足够了。

答案 1 :(得分:6)

一般来说,word是适合单个寄存器的数据量。

如果你使寄存器更窄,比如8位,那么需要多个周期才能增加2个32位的整数。

我也认为你希望你的RAM地址空间也适合一个单词。

答案 2 :(得分:2)

对于每个指令集,都有这些定义。例如,字节是8位或9位或一些其他大小。一个词被该架构定义为某种意义。

8086/8088将一个字节定义为8位,将一个字定义为16位。你有16位寄存器,但你也可以使用它们作为8位半寄存器ax是16位寄存器啊是ax的上半部分,al是下半部分。不典型,但他们是如何做到的。后来80x86 EAX成为32位寄存器,其中ax是下半部分,依此类推。由于一个字被定义为16位,因此EAX被定义为双字或双字。后来出现了64位寄存器......这种架构中的64位称为四字。

ARM将字节定义为8位,将半字定义为16位,将字定义为32位。其他人也这样做。

这是硬件级别。然后你进入编程语言,他们可以自由地改变定义以及可能想要利用typedef或语言中的任何东西创建或更改其他定义的程序员,并可以自由地制作他们想要的任何大小。语言大小不必与硬件匹配,有时这样做是个好主意,但他们不必这样做,这取决于任何人为特定目标实现编译器和/或后端。

关于浪费......

x86架构使用可变字长指令。这意味着有一些8位指令,一些16位指令,24位,32位,等等。您可能希望从一个寄存器移动到另一个寄存器,该指令可能只占用一个字节,但如果您想将16位值移入寄存器,则可能需要一个字节来表示我想立即将一个寄存器移入寄存器,然后两个字节来定义该指令的立即,三个字节总数。当存储器为8位宽时发明指令集,对于8位宽存储器系统,这是有意义的。现在我们使用32位和64位宽的内存系统,这非常痛苦。然而,指令集有8位寄存器,ah,al,bh,bl等,可以在8位寄存器上进行8位操作。因此,将bool或其他类似的东西放在一个字节大小以节省一些空间可能是有意义的。你可能已经把你的记忆切换到可变大小,无论如何也没有对齐,也可能。

ARM,思考传统的ARM(不是拇指/拇指2),指令总是32位宽,不多也不少。寄存器多于x86位,它们不分为半寄存器或字节大小的寄存器。你没有像比较等8位操作。一切都是32位,因为它完成寄存器注册(有一些小的立即,是的)。如果您的高级语言中的变量永远不会小于-5或大于+20,那么您可能希望使用高级语言中的有符号字节来节省一些空间。您会发现,有时您必须使用额外的指令来对数据进行扩展或屏蔽,以使用32位寄存器模拟8位操作。节省3个字节会花费你4或8或更多。 32位int比签名字节便宜。

存在对齐问题,因为x86允许未对齐访问(例如,使用32位数据总线从/向地址0x4进行32位读/写),这会花费额外的周期。 ARM和其他人不允许这样做。但同样地,即使通过缓存,字节写入也会导致读取 - 修改 - 写入,因为缓存可能是32位宽的内存。更改一个字节,你必须读取32位,修改8,然后写回32。耗费时钟周期。您是否使用了32位变量而不是8位变量,即使该变量可能永远不会超出-5到+20范围。你花费了更多的时钟周期。更浪费。

现在关于为什么具有8位寄存器的系统需要更多周期来添加32位数而不是32位系统的问题。你已经知道了这个问题的答案,因为你很可能去了小学并学会了用铅笔和纸张添加。

如果我想在允许3位数寄存器的世界中添加十进制数123 + 789,我可以在一个周期内执行该添加:

 110 <--- carry bits/numbers
 123
+789
====
 912

将其视为基于32位寄存器的系统。现在,对于基于8位寄存器的系统,世界一次只允许一个数字:

一个循环3 + 9,进位为0

 10 
  3
+ 9
====
  2

执行是1,我们必须执行该操作以获得执行所以我们可以使用它作为下一个操作的进位与下一组寄存器,下一个循环2 + 8与我们的进位1

 11 
  2
+ 8
====
  1

执行也是一个,第三个周期1 + 7,其中进位为1

 01
  1
+ 7
====
  9

如果我们需要,执行是0 ...

数字系统无关紧要(基数10,基数2等)它们的工作原理相同。

现在,如果您要问的问题是,例如,我有2和3并且想要将它们加在一起,那么在64位处理器中使用两个64位寄存器来执行它似乎是一个巨大的浪费一个只占用几列的操作。同样地将这些保存到存储器等等。对于布尔值或alu操作(添加或等),寄存器的宽度无关紧要,它是针对该宽度设计的,管道平均为一个时钟。无论如何,它都会执行64位添加。是的,这是浪费大量逻辑的房地产。如上所述,您可以选择使用更少的逻辑但更多的时钟或更多的逻辑和更少的时钟。更多的时钟解决方案也可能涉及更多的存储周期,耗费更多的时钟。较宽的变量可能会浪费更多的内存,但使用更少的时钟和更广泛的内存系统。这完全是一种权衡。现在逻辑在几千兆赫兹中最大化,内存非常缓慢但是通过使总线更宽和其他并行技巧,你可以使它看起来更快。如果你以牺牲时钟周期为代价来节省逻辑和内存的费用,那么你可能无法实时观看YouTube视频或者用足够的像素来查看即将发生的事情。或浏览网页,因为绘制通常使用数学函数压缩的字体和图像需要很长时间,用户无法忍受它。

我建议你看一下微芯片pic指令集

http://en.wikipedia.org/wiki/Microchip_PIC

上面列出的12位指令集表。想想你编写的最后一个程序,并用该指令集实现该程序。更好的是,使用pic指令集添加三个简单数字。它只有一个寄存器,做数学你必须得到一个操作数把它放在w寄存器中,用f寄存器执行数学运算,如果你不想弄乱f寄存器的内容就说,那你就离开了导致w寄存器。现在,添加另一个f寄存器,结果为w,然后将第三个寄存器,结果添加到w,然后将w保存在第四个f寄存器中。 d = a + b + c。当然,如果你只需要a,b,c进行那一次操作,你必须做三次读取然后添加,但是如果其中一个或多个操作数是其他操作的结果,则不需要是因为我们有更多的寄存器等存储到ram,你开始看到规模经济。 6502(表面上除非你理解零页)和其他指令集面向较少的逻辑,较少的ram以牺牲时钟周期为代价。对于较旧的设计(包括x86),这是因为逻辑制造和构建(相对)昂贵,而内存同样昂贵。

您可以将处理器的这种简化以牺牲时钟周期为代价,达到极限,一条指令。

http://en.wikipedia.org/wiki/Single_instruction_set_computer

opencores.org有一些这样的一个或几个指令处理器。

你提到java,如果你要在硬件中构建它,它的虚拟机的运行会牺牲时钟循环(带有可移植性的奖励)。有关基于堆栈的处理器(不是java,只是基于堆栈的解决方案的另一个示例)的示例,请参阅opencores中的zpu。当然不是用java发明的,pascal最初是基于堆栈的伪代码,然后你在目标上实现了伪代码。基于堆栈的解决方案基于堆栈的解决方案是基于堆栈的解决方案,它是基于堆栈的小型c生成的基于堆栈的程序,非常便携。但

对你的问题的简短回答,是不要过分关注微观,稍微退一步看全貌。我们在处理器中使用越来越大的寄存器的原因是因为速度,大多数时候你没有在64位处理器的alu操作中使用所有这些地址位或数据位,这是非常正确的,但是在你的时间里那些更广泛的寄存器,更广泛的总线和存储器会产生巨大的性能差异,足以弥补其他地方的浪费。无论如何浪费相当便宜,处理器,内存,磁盘空间,8位多千兆赫系统的成本如果需要提供相同的用户体验或足够接近,则不会比64位多千兆赫系统便宜8倍。同样的。

答案 3 :(得分:1)

它与总线宽度有关。处理器的每个时钟周期在总线宽度方面向前移动整个处理器,因此可能无法优化每个操作数类型的寄存器宽度。

答案 4 :(得分:0)

您可以使用架构的存储字节指令(通常将寄存器的低位位存储在存储器位置),从字大小的寄存器中将一个字节值存储在存储器中。

答案 5 :(得分:0)

许多早期计算机以较小的增量存储数据,通常为4位或6位数字。当数据路径很窄并且算术连续进行,一次一个数字时,这种方法工作得相当好。它的存储效率很高(这是一种珍贵的商品)。

存储不再那么珍贵 - 吞吐量是 - 并且计算机可以通过更宽的数据路径实现更好的吞吐量。

答案 6 :(得分:0)

要考虑的一件事:

&#34;现代&#34; (ca 1985)用于处理器设计的RISC方案考虑到在处理器芯片上放置相当多的相当宽的寄存器相对便宜,与成本&#34;成本相比。 (在芯片&#34;房地产&#34;)&#34;控制逻辑&#34;。

虽然有理由质疑这个论点的全部真实性,但它确实有一些事实要素,而且,虽然寄存器比同等数量的RAM多了许多倍(可能是1000或更多),但它和#39 ; s还相对便宜。将寄存器缩小并需要更多周期来完成相同的操作将是错误的经济。相反,设计师试图尽可能在一个周期内完成任务。