MIPS-以字节存储的字符与不以字节存储的字符是否相同?

时间:2018-08-30 12:26:51

标签: assembly mips mips32

我是MIPS的新手,我只是想知道,我通过以下方式存储空格字符:

li $t0, ' '
lb $t1, ' '

la $t2, myArray  # load array
sb $t0, 0($t2)   # myArray[0] = ' '

在这种情况下,$ t0 == $ t1吗? sb指令有效吗?我有点困惑的是我是否可以互换使用字节和整数(字)。

1 个答案:

答案 0 :(得分:0)

byteword不能自由互换,因为字节仅是8位信息,而word是32位信息(在MIPS平台上)。因此byte可以设置为256个不同的可能值(8个0/1位值的2 8 组合),而word可以设置为256 4 不同的可能值(32位模式)。

您需要四个字节来存储相同的可能的信息量,例如可以放入单个字中的信息(8位* 4 = 32位)。

但是,根据要处理的值,如果可以保证它们的范围,则可以预测字节/半字/字之间的代码转换值的行为,某些值是否会在这种转换中幸免于难,或者它需要额外的验证/处理。例如,如果您输入的值是ASCII字符(来自字符串),则这些值只有7位(当解释为带符号整数时,仅在ASCII中定义了0到+127的值)。

因此,例如li $t0, ' '将被汇编为li $t0, 32(因为“空格”字符在计算机中被编码为值32),并且由于li指令将立即数作为操作符带符号整数。

实际上,“ li”不是真正的MIPS指令,而是方便的伪指令,汇编程序会将其转换为一个/两个本机指令以编码/组成所需的立即数。尝试使用值+ 1,-1,+ 65000,-65000的li $t0, ...,并在调试器中观察如何将其组装为不同的本机指令,以实现所需的“立即加载”效果,例如-65000值需要至少要编写两个本机指令。

因此,从技术上讲,您正在将32位(字)值加载到$ t0中(即使' '仅是值32,也很容易放入字节中)。

但是,正如您所知,您确实已将ASCII码“空格”加载到t0中,无论t0是32位“宽”,您只知道将“字节”存储到内存中就足够了,例如,如果您要在缓冲区中创建新字符串,并且要在其中添加空格字符。因此sb $t0, 0($t2)是正确的。如果您在t0中有一个更大的值,则忽略高24位,并且仅使用sb指令将该值的低8位写入内存(有效地“截断”内存中的该值,无法从内存中读取完整值,仅读取截断的部分。


在MIPS汇编中,向其他方向的转换也经常发生,因为例如lb将仅从存储器中读取8位,但是会将它们符号扩展到完整的寄存器(32位)中。如果您不重视自己的价值观,那么您很容易陷入这样的困境:

.data
test_value: .byte 234
.text
    li      $t0, 234
    lb      $t1, test_value
    tne     $t0, $t1     # throw exception if t0 is not equal to t1
    # terminate normally when values are equal
    li      $v0, 10
    syscall

这可能是第一次读取,因为234与234比较,因此程序通常会终止,但是如果您尝试运行它,它将在tne指令处以异常结束。因为lb确实对值进行符号扩展,并且234仅在将位模式解释为“无符号8位整数”时才适合8位,因此如果将相同的位模式解释为“有符号8位”整数”,它将变为值-22。并且-22不等于234

如果将lb指令更改为lbu,该指令将加载“无符号字节”,该代码将正常工作并退出,因为tne将比较234与234的值,相等。

因此,在进行汇编编程时,您应该明确了解要处理的数据类型,并根据需要正确扩展/截断这些值。

(顺便说一句,MARS汇编器会警告您“ 234”不适合“有符号字节”和可能的截断-但最大255的值实际上适合8位,只需要以“无符号”方式解释..上面的值255将真正被截断,就像某些位完全丢失一样,例如.byte 1025将仅将值1存储在内存中