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