我正在努力掌握如何在 MIPS 中操作/比较存储在寄存器(字/半字/中间值)中的数据。如果它们各自代表不同的字节数有关系吗?例如,通过li加载一个立即数比如5,然后加载一个比如5的单词,最后用bne进行比较是否有效?
2 回答
如果它们各自代表不同的字节数有关系吗?
简短的回答:不,没关系,因为 5 是 5。
更长的答案:MIPS 寄存器都是 32 位宽,从某种意义上说,没有办法一次操作少于 32 位——除了字节和半字加载/存储指令(尽管即使这些加载也填充了完整的 32位寄存器)。
例如,如果您的数据在内存中并且是 8 位宽(例如字符或字节),并且是有符号(无符号)数据类型,那么您可以使用lb
( lbu
) 将其加载到 32 位寄存器中,同时使用符号(零)将 8 位值扩展到 32 位。在数值上,符号(零)扩展保持该值相同,因此您现在可以使用寄存器中的 32 位值。
(当然,您必须提前知道 8 位数据是否为数字,并且应该是符号与零扩展。我们在高级语言中通过逻辑变量的声明(和永久)数据类型知道这一点,但在汇编中,我们'正在使用没有永久数据类型的物理存储,所以当它很重要时,我们通过机器代码指令选择告诉处理器访问有符号或无符号的内存。)
如果您的数据不是 8 位或 16 位宽(或 32 位),您可以使用单个字节,或者从内存中加载比您感兴趣的更多的数据,并清除或签署与您无关的扩展位。
您知道 Cint
在与诸如+
?之类的运算符一起使用时如何隐式提升每个窄整数类型 该语言设计与 MIPS 之类的体系结构相匹配,这些体系结构本身没有 8 位或 16 位整数运算,只有int
/unsigned int
大小。(如果您确实使用多条指令来进行扩展精度数学,则范围更广)。
MIPS 指令总是将它们的立即数符号扩展为 32 位。(或按位布尔指令的零扩展。)
如果您以后只关心低位,则可以在不关心高位的情况下使用某些操作sb
,但是 MIPS 比较喜欢slt
或beq
总是查看所有位。 如果只需要结果的低位部分,哪些 2 的补码整数运算可以在不将输入中的高位归零的情况下使用?
在 C 中,将结果分配给一个窄整数会再次截断结果,这就像做sb
or sh
。(实际上在 C 中,它定义为模减少值以适应类型的值范围,但对于无符号或 2 的补码有符号整数,可以实现为位模式的截断。)
lb
有关使用vs.lbu
将符号或零扩展加载到 32 位的更多 asm 详细信息,另请参阅 Erik 的回答。
MIPS 的标准调用约定要求窄函数参数和返回值(例如char foo(short x)
正确符号扩展为完整寄存器宽度)并非巧合。有关更多信息,请参阅有关 ISA 如何处理窄数据的 x86-64 问题的 MIPS 比较脚注:MOVZX missing 32 bit register to 64 bit register