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