我知道当您在 SPARC CPU(和 MIPS)中读取 %r0 时,总是返回 0,但我想知道为什么?
这背后的设计决策是什么,为什么?
我知道当您在 SPARC CPU(和 MIPS)中读取 %r0 时,总是返回 0,但我想知道为什么?
这背后的设计决策是什么,为什么?
这只是 CPU 的设计方式。r0
一方面,确保始终设置为零是一种避免对一个非常常见的值进行潜在昂贵的内存访问的方法。
一方面(阅读),留出一个寄存器来保存零值是很方便的,这样您就可以使用它。否则,您必须自己将零加载到寄存器中。
许多 RISC 处理器倾向于在寄存器中进行数据操作,只为加载和存储操作访问内存。这不是 RISC 的硬性规定,更多的是一种趋势。留出一个寄存器以使您始终有零可用可能很有用 - 这是一种权衡,因为您可以减少一个寄存器用于通用值,但 MIPS 设计人员显然认为这是值得的。
另一方面(写作),因为r0
与零值相关,你可以把你想要的东西放在那里,它不会有任何区别——它会保持为零。这意味着如果您想丢弃该值,可以将其用作目标。
同样,这与 RISC 背后的理念有关。它倾向于支持极少数指令格式,例如 MIPSR
和I
格式J
(寄存器、立即数和跳转)。例如,您可以拥有一组始终存储结果的集合,而不是根据您是否要存储结果来使用多种指令格式,然后r0
如果您不关心它,只需将其存储到其中。
因此,如果您想检查添加两个寄存器是否会导致溢出但又不想将结果存储在任何地方,您可以使用:
add $0, $7, $8 ; r0 <- r7 + r8, but r0 remains at 0.
MIPS 文档MIPS32 Architecture for Programmers Volume I: Introduction to the MIPS32 Architecture
证实了上述内容:
R0 被硬连线为零值,并且可以用作任何要丢弃其结果的指令的目标寄存器。当需要零值时,R0 也可以用作源。
从指令集设计的角度来看,主要原因是/dev/null
-register 的存在允许将原本必须是两条(或更多)不同的指令的某些“压缩”成一条。几个例子:
call
和return
,使用链接寄存器,可以用一条指令完成:
jmp <tgtreg>,<pc>,<linkreg>
jmp
是原子的mov <pc>,<linkreg>; mov <tgtreg>,<pc>
),和jmp <linkreg>,<nullreg>,<nullreg>
cmp
或者tst
可以是一个简单的sub <a>,<b>,<nullreg>
这些完整的表格可以从 Oracle 的文档、SPARC 综合指令和sparcv9 综合指令中找到;其中大部分涉及%g0
某个地方。