MIPS - 存储为字节的字符与未存储为字节的字符相同吗?

MIPS - Are characters which are stored as bytes the same as those not stored as bytes?

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

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

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

在这种情况下是$t0 == $t1? sb 指令是否有效?我有点困惑的是我是否可以互换使用 byte 和 ints(words)。

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

您需要四个字节来存储与您可以装入单个字(8 位 * 4 = 32 位)的信息量相同的可能数量。

但是根据您正在处理的值,如果您可以保证它们的范围,则可以预测 byte/half-word/word 之间的代码转换值的行为方式,某些值是否会在此类转换中幸存下来而不会受到任何损坏,或者它需要额外的 validation/handling。例如,如果您的输入值是 ASCII 字符(来自字符串),那么它们只有 7 位(当解释为带符号的整数时,ASCII 中只定义了值 0 到 +127)。

因此,例如 li $t0, ' ' 将 assemble 作为 li $t0, 32(因为 "space" 字符在计算机中编码为值 32)并且因为 li指令将立即数作为操作符号整数。

实际上 "li" 不是真正的 MIPS 指令,而是一种方便的伪指令,assembler 会将其转换为 one/two 本机指令 encode/compose期望的即时值。例如尝试使用值 +1、-1、+65000、-65000 的 li $t0, ... 并在调试器中观察它如何将 assembled 转换为不同的本机指令,从而实现所需的 "load immediate" 效果,因为例如,-65000 值需要至少两个本机指令才能组成。

所以你在技术上将 32 位(字)值加载到 $t0(即使 ' ' 只是值 32,很容易放入字节)。

但是你知道你确实将 ASCII "space" 加载到 t0,不管 t0 是 32 位 "wide",你知道它足以存储只有 "byte" 进入内存,例如,如果你在缓冲区中创建新字符串,并且你想将 space 字符放入其中。那么 sb $t0, 0($t2) 是正确的。如果你在 t0 中有一些更大的值,高 24 位被忽略,并且只有该值的低 8 位用 sb 指令写入内存(实际上 "truncating" 该值在内存,不可能从内存中读回完整的值,只能读回 t运行 的部分)。


其他方向的转换在 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 进行比较,因此程序通常会终止,但如果您尝试 运行 它,它会在 [= 处以异常结束28=] 指令。因为 lb 确实对值进行符号扩展并且 234 仅当您将该位模式解释为 "unsigned 8 bit integer" 时才适合 8 位,如果您将相同的位模式解释为 "signed 8 bit integer" , 它变成值 -22-22 不等于 234.

您能否将 lb 指令更改为 lbu,加载 "unsigned byte",代码将正常运行并退出,因为 tne 将比较 234 与 234值,它们是相等的。

因此,在使用汇编编程时,您应该清楚地了解您处理的数据类型,并根据需要正确地 extend/truncate 这些值。

(顺便说一句,MARS assembler 会警告您“234”不适合 "signed byte" 和可能的 t运行cation - 但最大 255 的值实际上适合 8 位,只需要以 "unsigned" 方式解释.. 255 以上的值将得到真正的 t运行 处理,就像某些位完全丢失一样,例如 .byte 1025 将仅存储在内存中值 1)