对mips I-Type指令语法感到困惑
confused over mips I-Type Instruction syntax
抱歉这个非常愚蠢的问题。但是我整天都在看我的课本,它变得非常混乱。
我想用 MIPS I 型指令澄清一些与语法相关的问题。
我理解
addi , , -50
是可能的,立即数被解释为小数(2s 补码)。
但是我可以这样写 addi , , 0xF1DF?
使得立即数是十六进制的吗?
这让我想到了 andi , , 0xFFFF
和 ori , [=13=], 0x0FA5
的下一个问题。我知道这 2 个代码是正确的。
但是我可以写 andi , , 120
和 ori , [=15=], -16
使得立即值是十进制的吗?如果可能的话,它是将 120
解释为十六进制还是将十进制 120
转换为十六进制等于十六进制的 78
。
我很迷茫
您可以用 10 进制或十六进制表示立即数。要表示十进制值,您需要在数字前使用 0x
前缀(例如 0x10
,即以 10 为基数的 16
)。如果您不在数字前使用前缀 0x
,汇编程序将假定数字是十进制表示法。
使用您的示例,如果您想添加 120
(基数 10),您应该像 addi , , 120
或 addi , , 0x78
那样对指令进行编码。汇编程序将生成相同的二进制指令 0x20000000
。您可以使用此在线汇编程序亲自尝试 here。
MIPS addi
/ addiu
将 16 位立即数符号扩展为 32 位 (2's complement):
从 -32768
(0xFFFF8000) 到 32767
(0x00007FFFF) 的值是可编码的。
MIPS andi
/ ori
zero-将16位立即数扩展为32位,
从 0
(0x00000000) 到 65535
(0x0000FFFFF) 的值是可编码的。
所以不,你不能写ori , [=19=], -16
,你必须使用addiu
。
(或者效率低下,lui , 0xFFFF
/ ori , , 0xfff0
)。
通常你可以把这个决定交给assembler,让它选择如何用li , 0xFFFFFFF0
或li , -16
创建常量。这些将 assemble 完全相同。
但是如果您不只是创建一个常量,您就必须知道什么是可编码的。例如on the Godbolt compiler explorer,gcc5.4针对MIPS编译这些函数如下:
unsigned mask(unsigned a) {
return a & -16UL;
}
# not encodeable as an immediate for andi
li ,-16 # 0xfffffffffffffff0
j
and ,,
unsigned mask_positive(unsigned a) {
return a & 0xFF;
}
j
andi ,,0x00ff # encodeable as an immediate
源中的表示完全不相关;十六进制和十进制是两种不同的数字序列化格式。 0x10
和 16
字面意思是一样的。 在 MIPS 机器代码中,它们以 16 位二进制存储,而不是十六进制或十进制
-32768
和 0xFFFF8000
也是一回事(在 32 位 2 的补码中)。它也是 16 位 2 的补码中的 0x8000
。而且它不能表示为 16 位无符号数,因为 0x8000
零扩展到 0x00008000
(+32768).
抱歉这个非常愚蠢的问题。但是我整天都在看我的课本,它变得非常混乱。
我想用 MIPS I 型指令澄清一些与语法相关的问题。
我理解
addi , , -50
是可能的,立即数被解释为小数(2s 补码)。
但是我可以这样写 addi , , 0xF1DF?
使得立即数是十六进制的吗?
这让我想到了 andi , , 0xFFFF
和 ori , [=13=], 0x0FA5
的下一个问题。我知道这 2 个代码是正确的。
但是我可以写 andi , , 120
和 ori , [=15=], -16
使得立即值是十进制的吗?如果可能的话,它是将 120
解释为十六进制还是将十进制 120
转换为十六进制等于十六进制的 78
。
我很迷茫
您可以用 10 进制或十六进制表示立即数。要表示十进制值,您需要在数字前使用 0x
前缀(例如 0x10
,即以 10 为基数的 16
)。如果您不在数字前使用前缀 0x
,汇编程序将假定数字是十进制表示法。
使用您的示例,如果您想添加 120
(基数 10),您应该像 addi , , 120
或 addi , , 0x78
那样对指令进行编码。汇编程序将生成相同的二进制指令 0x20000000
。您可以使用此在线汇编程序亲自尝试 here。
MIPS addi
/ addiu
将 16 位立即数符号扩展为 32 位 (2's complement):
从 -32768
(0xFFFF8000) 到 32767
(0x00007FFFF) 的值是可编码的。
MIPS andi
/ ori
zero-将16位立即数扩展为32位,
从 0
(0x00000000) 到 65535
(0x0000FFFFF) 的值是可编码的。
所以不,你不能写ori , [=19=], -16
,你必须使用addiu
。
(或者效率低下,lui , 0xFFFF
/ ori , , 0xfff0
)。
通常你可以把这个决定交给assembler,让它选择如何用li , 0xFFFFFFF0
或li , -16
创建常量。这些将 assemble 完全相同。
但是如果您不只是创建一个常量,您就必须知道什么是可编码的。例如on the Godbolt compiler explorer,gcc5.4针对MIPS编译这些函数如下:
unsigned mask(unsigned a) {
return a & -16UL;
}
# not encodeable as an immediate for andi
li ,-16 # 0xfffffffffffffff0
j
and ,,
unsigned mask_positive(unsigned a) {
return a & 0xFF;
}
j
andi ,,0x00ff # encodeable as an immediate
源中的表示完全不相关;十六进制和十进制是两种不同的数字序列化格式。 0x10
和 16
字面意思是一样的。 在 MIPS 机器代码中,它们以 16 位二进制存储,而不是十六进制或十进制
-32768
和 0xFFFF8000
也是一回事(在 32 位 2 的补码中)。它也是 16 位 2 的补码中的 0x8000
。而且它不能表示为 16 位无符号数,因为 0x8000
零扩展到 0x00008000
(+32768).