MARS MIPS 模拟器 ASCII 字符串未正确存储在小端内存中?
MARS MIPS Simulator ASCII string not storing in memory in little-endian properly?
我听说 MARS MIPS 模拟器是小端的,所以我希望如果我在内存中使用 .asciiz "HELLO"
保留字符串“HELLO”,我会找到字符 O
位于给定字符串的最低内存地址中,H
位于给定字符串的最高内存地址中。
但是当我组装代码时,MARS 的调试器显示内存如下:
H
存放在0x10010000地址(数据段基地址)而O
存放在0x10010004——显然存放在更高的内存地址。这不是大端吗?
但是,我注意到当我使用 .word 0xABCD
保留像 0x0000ABCD
这样的字长数据时,D
将被放置在最低内存中,就像小端一样系统必须做的。为什么他们以不同的方式存储数据?
字符串是一个字节序列,而不是一个巨大的整数。无论机器字节序如何,字符串的第一个字节始终是最低地址。
机器字节序只决定了你在寄存器中得到的值,如果你这样做了lw $t0, my_string
。
但是如果你用 lbu $a0, ($t1)
/ addiu $t1, $t1, 1
遍历字符串的字节,你肯定想按照你在源代码中写入的顺序获取 ASCII 字节:H,E, L, L, O, 0
.
如果要向后存储字符串,请使用 .asciiz "OLLEH"
。
字节流没有结尾,只有 CPU 可以通过单次访问加载的内容。 endianness 的整个概念来自能够访问单词的各个字节,例如sw
然后 lbu
.
如果你可以只使用lw
/sw
那么硬件字节顺序就不是问题了,这将取决于软件如何转移/ OR 或 AND 访问 32 位整数中的位,如果它想打包 8 位 ASCII 字符。或者,如果您 仅 甚至可以使用 lbu
/ sb
,则由软件决定存储较长整数的单独字节的顺序。
对于字符串,每个人都会做出明智的选择,以打印顺序存储它们,第一个字节在最低地址。这恰好与您希望它们在文本文件中或在一行内从左到右扫描的视频 RAM 中的顺序相匹配。
所以,当你实现一个高效的 strlen
时,字节顺序只对字符串很重要,它一次检查 4 个字节 0
,使用 bithack 或其他东西:https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord .
虽然那个 bithack 实际上并没有告诉你 区别在哪里,所以也许一个更好的例子是如果你通过比较 4 个字节来实现 strcmp
( 1 个单词)一次。如果不匹配,您可以在这些单词中一次循环 1 个字节以找到不同的确切字符,或者您可以将两个单词异或在一起,然后找到最低设置位(小端)或最高位的位置设置位(big-endian)以找出哪个字节包含第一个位差。 (我不知道 MIPS 是否有 clz
/ ctz
计数前导/尾随零指令,但如果有,你可以这样使用它们。)
我听说 MARS MIPS 模拟器是小端的,所以我希望如果我在内存中使用 .asciiz "HELLO"
保留字符串“HELLO”,我会找到字符 O
位于给定字符串的最低内存地址中,H
位于给定字符串的最高内存地址中。
但是当我组装代码时,MARS 的调试器显示内存如下:
H
存放在0x10010000地址(数据段基地址)而O
存放在0x10010004——显然存放在更高的内存地址。这不是大端吗?
但是,我注意到当我使用 .word 0xABCD
保留像 0x0000ABCD
这样的字长数据时,D
将被放置在最低内存中,就像小端一样系统必须做的。为什么他们以不同的方式存储数据?
字符串是一个字节序列,而不是一个巨大的整数。无论机器字节序如何,字符串的第一个字节始终是最低地址。
机器字节序只决定了你在寄存器中得到的值,如果你这样做了lw $t0, my_string
。
但是如果你用 lbu $a0, ($t1)
/ addiu $t1, $t1, 1
遍历字符串的字节,你肯定想按照你在源代码中写入的顺序获取 ASCII 字节:H,E, L, L, O, 0
.
如果要向后存储字符串,请使用 .asciiz "OLLEH"
。
字节流没有结尾,只有 CPU 可以通过单次访问加载的内容。 endianness 的整个概念来自能够访问单词的各个字节,例如sw
然后 lbu
.
如果你可以只使用lw
/sw
那么硬件字节顺序就不是问题了,这将取决于软件如何转移/ OR 或 AND 访问 32 位整数中的位,如果它想打包 8 位 ASCII 字符。或者,如果您 仅 甚至可以使用 lbu
/ sb
,则由软件决定存储较长整数的单独字节的顺序。
对于字符串,每个人都会做出明智的选择,以打印顺序存储它们,第一个字节在最低地址。这恰好与您希望它们在文本文件中或在一行内从左到右扫描的视频 RAM 中的顺序相匹配。
所以,当你实现一个高效的 strlen
时,字节顺序只对字符串很重要,它一次检查 4 个字节 0
,使用 bithack 或其他东西:https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord .
虽然那个 bithack 实际上并没有告诉你 区别在哪里,所以也许一个更好的例子是如果你通过比较 4 个字节来实现 strcmp
( 1 个单词)一次。如果不匹配,您可以在这些单词中一次循环 1 个字节以找到不同的确切字符,或者您可以将两个单词异或在一起,然后找到最低设置位(小端)或最高位的位置设置位(big-endian)以找出哪个字节包含第一个位差。 (我不知道 MIPS 是否有 clz
/ ctz
计数前导/尾随零指令,但如果有,你可以这样使用它们。)