在aarch64中,零寄存器'zr'本质上是一个通用寄存器吗?

6
最近开始涉及AArch64汇编,我注意到它有一个专门为零分配的寄存器,而在(大多数)其他架构中,你只需要使用“xor var,var”来实现。我阅读的关于“zr”的网站将其解释为“零的参考点”,听起来很像我在直流电子学中定义地面的方式。因为ARM被业余爱好者使用,将电路中的地线与代码中的零联系起来对我来说有些合理。我知道这比我的解释复杂得多,但这个类比是安全的吗?相比其他获取“0”的方法,使用这个寄存器会产生不同的结果吗?

4
相比之下,大多数其他架构只需执行“xor var, var”操作。实际上,现代(自20世纪80年代以来)大多数架构都是RISC并具有专用的零寄存器,例如MIPS - phuclv
5
实现AArch64架构的ARM CPU是复杂的CPU。它们包括一些可能与不执行x86指令集的任何CPU一样复杂的CPU。它们并不是为爱好者设计的。 - Ross Ridge
5个回答

17

零寄存器xzr或者wzr是Aarch64 ISA中的一个巧妙设计。它的寄存器编号是31,就像堆栈指针spwsp一样。根据上下文,寄存器号31将指代其中之一。

这个巧妙的设计让Aarch64 ISA简化了其指令集。例如,cmp xn,xm指令实际上是subs xzr,xn,xm,即减法并丢弃结果。而mov xn,xm只是一个orr xn,xzr,xm,即将源与零进行按位或。寄存器31只有在有意义的情况下才被识别为堆栈指针,并且指令集被聪明地选择,以便您几乎永远不会遇到此限制。


6
“zr”寄存器在aarch64中是否本质上是地线?这个类比是否正确?
不是。有各种硬件逻辑存在。零寄存器的位是否连接到地面并不重要,因为它只是一个实现细节。您只需要将其视为数字值零以及读取或写入该寄存器时会发生什么。在软件中工作时,不要考虑底层电路。
例如,许多架构可能使用反向逻辑(active-low),其中0V表示逻辑1,则零寄存器实际上将连接到Vcc。或者其他一些使用平衡逻辑,其中逻辑0和1分别由−Vcc和Vcc表示。在那种情况下,零寄存器将连接到−Vcc,它也不是地面。

但为什么要有一个零寄存器呢?

通常的RISC理念是避免在每个指令中访问内存,而是只允许加载/存储指令接触内存。因此,RISC架构需要大量的寄存器来减少溢出到内存的需求。

几乎所有其他RISC架构都至少有32个寄存器,因此值得为零常量专门分配一个寄存器。我们可以看到:SPARC%g0MIPS$zero$0Itanium(严格来说不是RISC而是VLIW,但仍然有大量寄存器[128])有r0RISC-Vx0SH-5R63BlackfinR0i860R0PA-RISCR0ARC%r0Motorola 88000r0Alpha有两个独立的零寄存器:整数R31和浮点F31...

在PowerPC中,稍微有点偏差,其中r0根据指令的不同可以表示GPR0或数字0。然而,PowerPC的Plan 9甚至进一步偏离,通过软件r0初始化为0

唯一一种拥有32个寄存器但没有零寄存器的奇怪RISC体系结构是Intel i960,但同样奇异的Plan 9也需要软件将R3寄存器设置为0。另一种奇怪的体系结构是OpenRISC,其中R0也由软件初始化为0。这意味着不应将R0用作目标,因为对其进行写入将破坏值。
寄存器0允许设计者删除许多指令,简化硬件。例如,我们不再需要mov,而是可以使用零进行add并将其存储在目标中。否定现在也只是从零减去。对零寄存器的写入会丢弃结果,我们也不需要单独的NOP。ARM和英特尔i960没有零寄存器,因此它们在ISA中有显式的mov指令。
ARM一直是一个例外,因为它只有16个寄存器(实际上约为12-13,因为SP、PC等包含在通用寄存器集中),为零专门分配一个寄存器是浪费的。此外,ARM被认为不是纯RISC,因为其指令和寻址模式过于复杂(每个指令都有LDM、STM、移位和条件...)。
尽管ARM是一种RISC架构,但它并不像MIPS那样严格遵循RISC原则。例如,一些ARM指令,如ldmstm,并不是简单的指令。此外,它提供了大量的寻址模式,并使用了相对复杂的指令格式。 RISC处理器指南:面向程序员和工程师 当Arm Holdings决定Aarch64也将拥有32个寄存器时,他们肯定会做同样的事情,使指令集更加RISCy和正交。现在PC、SP...也被分开了,因此我们拥有的寄存器数量比ARM多两倍以上。将其中一个寄存器作为零寄存器是非常有意义的。
类似的情况发生在SuperH架构中,其中版本SH-4有16个寄存器。当Renesas将其扩展到SH-5时,他们还为零常数保留了R63。

ARM不太RISCy的最大原因是load-multiple/store-multiple执行可变数量的加载或存储,基本上必须进行微代码编码。像2个寄存器通过通常的barrel-shifter进行缩放这样的复杂寻址模式对于现代CPU来说并不是什么大问题。AArch64取消了预测和ldm/stm,但保留了barrel shifter。当然,成为RISCy并不是他们的目标,而是一种紧凑的指令集,可以高效地实现,并且每个指令可以完成很多工作。(而且大多数实现仍然希望运行32位代码,因此需要硬件支持) - Peter Cordes
无论如何,如果你只想从那个引用中总结一件事情,对我来说它是ldm/stm,而不是寻址模式。 - Peter Cordes
是的,这个引用确实是关于加载/存储多个的,不过我记得在 Reddit 或其他地方读到一些关于 ARM 的其他复杂性的帖子,但我还没有重新检查。无论如何,我的观点是,在过渡到 64 位的同时,ARM 正在使架构更加 RISCy,并且零寄存器是其中的一步。 - phuclv

4
为了回答我认为是你的主要问题,,我不认为这是一个特别“安全”(有用)的比喻。
在电气工程中,接地的概念具有非常具体的语义和许多相关概念,但与“固定的零寄存器”只有非常间接的关系,因为两种情况都涉及数字零。
除了这两个概念中都有零的存在之外,我不认为这个比喻有太多用处。它几乎肯定不能反映出寄存器的实现方式的真实情况,也不能让您将电气工程知识中的概念映射到ARM汇编程序设计中。如果您有一个关于零寄存器如何工作的问题(例如,“写入时会发生什么?”),那么很可能无法通过参考您的类比来回答它。
我不知道为什么(未链接的)网站使用了术语参考点来表示零,但我认为完全可以忽略“参考点”语言。它只是零。当你读取它时是零,当你向它写入时它什么也不做。这种用途在fuz's answer中得到了解释。

总之,如果您发现这个比喻对您有用,那么在自己的学习过程中使用它并不是错误的!


3
您可以将此寄存器中的位看作是硬连接到地线。但写入它不会导致短路。更好的类比是Unix /dev/zero:舍弃写入,读取为一系列无限的零字节。
但是,它不是“参考”,因为事物是相对于它来测量的意义。逻辑0位可以存在于CPU中,无论AArch64是否有这个寄存器,它们都不会与其进行比较以确定它们是真/假。从电学上讲,逻辑1通常是高电压,0= 地线,所以门将它们的输入与地线进行比较,并且任何地方的所有0位都等同于地线。(这可能是一个重要的简化,当然,在ALU内部或其他某种表示形式中,位可能被反转或不存在,仅在逻辑上存在)。
因此,作为比喻,它根本不起作用。作为它的物理/电学实现的描述,也不完全适用。它需要舍弃写入而不会短路。在具有寄存器重命名功能的CPU中,需要在RAT(寄存器分配表)中特殊处理它,以跟踪写入被丢弃和依赖链不会通过xzr传播的事实。如果忽略这一点,您可以想象一个SRAM单元的替代品,其输入被断开,输出被硬连接到零。
它看起来像笨拙的措辞;更好的描述是零寄存器是一个固定的常数,静默地舍弃写入。
读取它会给您一个固定的常数零,有时很有用(例如,将零存储到内存中而无需先清空寄存器)。除非该上下文将为您提供相同寄存器编号的sp别名;我对AArch64不是很了解。

3
回答“否”不是更好吗?在电子学中,“地”这个术语具有非常特定且有点复杂的含义。我认为最好完全阻止这种思维方式。我不是一名电子工程师,但据我所见,数字电路的输出通常并没有真正连接到地,而是可以通过将能量释放到其他地方来使其处于与地相同的电位水平。例如,反向放大器就是这样工作的(如果我没记错的话)。 - Margaret Bloom
@MargaretBloom:好的反馈,已更新。但在CMOS逻辑中,“0”/假状态确实是通过开启连接输出至地的场效应晶体管(FET),并具有接近于零的电阻来创建的。一些瞬态电流会流过来放电负载的电容,然后就几乎没有了。请参阅维基百科https://en.wikipedia.org/wiki/CMOS上2晶体管非门的图像。当两个晶体管在开关中间部分导通时,某些电流确实会从VCC流向地。这就是为什么CMOS逻辑只在*开关时耗散功率,而另外一些完全关闭的晶体管则具有静态泄漏。 - Peter Cordes
@MargaretBloom:CMOS的非门就是一个反相放大器,但是它不是使用来自Vcc的电阻,而是使用另一个晶体管。因此,在输入高电平时,来自Vcc的晶体管具有接近无限的电阻,底部晶体管处于导通状态。在输入低电平时,底部晶体管被关闭。但是,与反相线性放大器通过固定电阻来为负载供电不同,来自Vcc的电流通过完全开启的晶体管流过。 - Peter Cordes
相关:为什么计算机中要使用NAND门制作AND门?解释了为什么逻辑门不是用晶体管/电阻器构建的,以及为什么反相对于门的扇出/级联是必要的,因此你不能只是将两个晶体管串联从Vcc到输出。 - Peter Cordes
一个CMOS反相器并不被认为是一个反相放大器,它们看起来可能很相似,但它们工作在完全不同的原理上。 我的观点是,在这个缩放级别下,谈论地和与之连接的事物或者"地=0"是没有意义的 :) 但我有些过于热心了,CPU不需要驱动高负载,所以在这些设计中,接地节点通常通过某些路径连接到地上 (但这些路径并不像那个NOT图中描绘的那样简单)。 - Margaret Bloom
1
顺便提一下,这个8085寄存器文件的正则表达式可能会引起您的兴趣。话说题外话,ECL技术与CMOS不同,它需要更多的功率,但速度更快,这对于某些深度ALU电路(如乘法器而不是寄存器文件)非常有用,并且可以通过一些开销按需开关。 - Margaret Bloom

-1
大部分是的
下面的Verilog代码展示了其中一个典型实现。 zr 总是连接到 0(即地线)。当软件代码尝试写入 zr 寄存器时,低级硬件电路通过简单地忽略写操作而保持不变。
always@(posedge clk, negedge rst_n) begin
  if(~rst_n) begin // set initial value when reset released.
    zr <= 32'b0;
  end else if(re) begin // only respond to the read operation
    zr <= 32'b0;
end

“if(~rst_n) begin”这部分是否相关?您明确指定读取值为0,因此甚至不需要任何存储来初始化。而且它的值并不重要。我不了解Verilog,但这似乎比零寄存器所需的逻辑更多。(虽然如果它做到了评论所说的,那么这是一个正确的实现,只是可能不是最优的。) - Peter Cordes
@PeterCordes,你对这里的小疑问是正确的。if(~rst_n) begin在逻辑上确实不必要为nz的初始目的。我刚意识到我不应该写出来。但是不用担心,加上if(~rst_n) begin当然是逻辑上正确的(这是电路设计中最常见的做法)。感谢你指出这一点。 - Zhaoyang
“tied to 0 (i.e., ground)” 谁说逻辑 0 是地线? - phuclv

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接