widening/narrowing 数据的字节顺序
Endianness when it comes to widening/narrowing data
在使用 MIPS 几个月后,我又开始阅读字节序了。当它来的时候我有点困惑
到什么时候 loading/storing from/to 内存很重要,所以有人可以验证我的理解是否正确?我没有 Big Endian 机器来测试它,并且出于某种原因无法让 qemu 工作。
Example 1:
lw $t0,word_
word_: .word 0xAABBCCDD // behaves the same in both Endian and Little Endian
Example 2:
lw $t0,bytearr_
bytearr_ : .byte 0xAB, 0xCD, 0xEF, 0xAA // either 0xABCDEFAA on BE or 0xAAEFCDAB on LE (?)
Example 3:
lhw $t0,b2hw
b2hw : .byte 0xAB, 0xCD //can this lead to issues as well? (LE is 0xCDAB, BE is 0xABCD)
如果我错了或者我遗漏了任何可能从一种字节序到另一种字节序可能出错的潜在转换,请纠正我。谢谢!
编辑:
在 LE/BE 的情况下,如果我尝试将一个词加载到一个半字中或将一个半字加载到一个词中,会发生什么情况?例如 lw $t0, hw_
其中 hw_: .half 0xABCD
和 lhw $t0, w_
其中 w_: .word 0xAABBCCDD
在示例 1 中,汇编程序负责如何在内存中排列单词。
如果体系结构是小端,则最低地址将包含 0xDD
,然后是 0xCC
,然后是 0xBB
,然后是 0xAA
。
如果架构是大端架构,则相反:首先是 0xAA
,然后是 0xBB
,然后是 0xCC
,然后是 0xDD
。
因此,当您发出 lw $t0, word_
时,您会得到您期望的值 (0xAABBCCDD
)。
在你的第二个例子中你定义了一个字节数组,所以汇编程序必须服从你的命令。最低地址将保存 0xAB
,然后是 0xCD
,然后是 0xEF
,然后是 0xAA
。
因此,当您发出 lw $t0,bytearr_
时,无论您的体系结构是小端还是大端,您都会得到不同的结果。
如果您的体系结构是小端,您最终会得到 $t0=0xAAEFCDAB
,如果您的体系结构是大端,您最终会得到 $t0=0xABCDEFAA
。
第三个例子和第二个类似。您定义了一个字节数组,因此最低地址将保存 0xAB
,然后是 0xCD
,如果体系结构是小端,则发出 lhw $t0, b2hw
将以 $t0=0xCDAB
结尾,并且 $t0=0xABCD
如果是大端。
如果您希望让汇编程序管理排列,那么您可以使用指令 .half
,如下所示:
lhw $t0,b2hw
b2hw : .half 0xABCD //let the assembler figure out how to arrange this half word in memory
你的最后一个问题是当你“试图将一个词加载到一个半字或将一个半字加载到一个词时会发生什么?”。
答案是你真的不会将一个词加载到一个半字中,也不会将一个半字加载到一个词中。您从某个地址开始加载一个字或半字。
因此,如果您有以下示例:
hw_: .half 0xABCD
w_: .word 0xAABBCCDD
此代码:
lw $t0, hw_
将从hw_
指向的地址开始加载一个字,
lhw $t0, w_
将从h_
指向的地址开始加载一个半字。
内存中的排列将是(从较小的地址到较大的地址):
如果是小端:
0xCD ; hw_
0xAB
0xDD ; w_
0xCC
0xBB
0xAA
所以如果你发出 lw $t0, hw_
你会得到 0xCCDDABCD
,而 lhw $t0, w_
你会得到 0xCCDD
.
如果是大端:
0xAB ; hw_
0xCD
0xAA ; w_
0xBB
0xCC
0xDD
所以如果你发出 lw $t0, hw_
你会得到 0xABCDAABB
,而 lhw $t0, w_
你会得到 0xAABB
.
在使用 MIPS 几个月后,我又开始阅读字节序了。当它来的时候我有点困惑 到什么时候 loading/storing from/to 内存很重要,所以有人可以验证我的理解是否正确?我没有 Big Endian 机器来测试它,并且出于某种原因无法让 qemu 工作。
Example 1:
lw $t0,word_
word_: .word 0xAABBCCDD // behaves the same in both Endian and Little Endian
Example 2:
lw $t0,bytearr_
bytearr_ : .byte 0xAB, 0xCD, 0xEF, 0xAA // either 0xABCDEFAA on BE or 0xAAEFCDAB on LE (?)
Example 3:
lhw $t0,b2hw
b2hw : .byte 0xAB, 0xCD //can this lead to issues as well? (LE is 0xCDAB, BE is 0xABCD)
如果我错了或者我遗漏了任何可能从一种字节序到另一种字节序可能出错的潜在转换,请纠正我。谢谢!
编辑:
在 LE/BE 的情况下,如果我尝试将一个词加载到一个半字中或将一个半字加载到一个词中,会发生什么情况?例如 lw $t0, hw_
其中 hw_: .half 0xABCD
和 lhw $t0, w_
其中 w_: .word 0xAABBCCDD
在示例 1 中,汇编程序负责如何在内存中排列单词。
如果体系结构是小端,则最低地址将包含 0xDD
,然后是 0xCC
,然后是 0xBB
,然后是 0xAA
。
如果架构是大端架构,则相反:首先是 0xAA
,然后是 0xBB
,然后是 0xCC
,然后是 0xDD
。
因此,当您发出 lw $t0, word_
时,您会得到您期望的值 (0xAABBCCDD
)。
在你的第二个例子中你定义了一个字节数组,所以汇编程序必须服从你的命令。最低地址将保存 0xAB
,然后是 0xCD
,然后是 0xEF
,然后是 0xAA
。
因此,当您发出 lw $t0,bytearr_
时,无论您的体系结构是小端还是大端,您都会得到不同的结果。
如果您的体系结构是小端,您最终会得到 $t0=0xAAEFCDAB
,如果您的体系结构是大端,您最终会得到 $t0=0xABCDEFAA
。
第三个例子和第二个类似。您定义了一个字节数组,因此最低地址将保存 0xAB
,然后是 0xCD
,如果体系结构是小端,则发出 lhw $t0, b2hw
将以 $t0=0xCDAB
结尾,并且 $t0=0xABCD
如果是大端。
如果您希望让汇编程序管理排列,那么您可以使用指令 .half
,如下所示:
lhw $t0,b2hw
b2hw : .half 0xABCD //let the assembler figure out how to arrange this half word in memory
你的最后一个问题是当你“试图将一个词加载到一个半字或将一个半字加载到一个词时会发生什么?”。
答案是你真的不会将一个词加载到一个半字中,也不会将一个半字加载到一个词中。您从某个地址开始加载一个字或半字。 因此,如果您有以下示例:
hw_: .half 0xABCD
w_: .word 0xAABBCCDD
此代码:
lw $t0, hw_
将从hw_
指向的地址开始加载一个字,
lhw $t0, w_
将从h_
指向的地址开始加载一个半字。
内存中的排列将是(从较小的地址到较大的地址):
如果是小端:
0xCD ; hw_
0xAB
0xDD ; w_
0xCC
0xBB
0xAA
所以如果你发出 lw $t0, hw_
你会得到 0xCCDDABCD
,而 lhw $t0, w_
你会得到 0xCCDD
.
如果是大端:
0xAB ; hw_
0xCD
0xAA ; w_
0xBB
0xCC
0xDD
所以如果你发出 lw $t0, hw_
你会得到 0xABCDAABB
,而 lhw $t0, w_
你会得到 0xAABB
.