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)。
byte
与word
不能自由互换,因为字节只有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
)
我是 MIPS 的新手,我只是想知道,我通过以下方式存储 space 字符:
li $t0, ' '
lb $t1, ' '
la $t2, myArray # load array
sb $t0, 0($t2) # myArray[0] = ' '
在这种情况下是$t0 == $t1? sb 指令是否有效?我有点困惑的是我是否可以互换使用 byte 和 ints(words)。
byte
与word
不能自由互换,因为字节只有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
)