计组与微机控制
3.8 数据组织
3.8 数据组织
计算机内存以字节编址,但数据可以是:
- 字节;- 半字;- 字;- 双字;- 字符串;
- 数组;- 结构体。
问题:
> 多字节数据在连续字节中按什么顺序存放?
这引出端格式。
一.1.数据组织与端格式:

端格式决定多字节数据的高低字节在内存中的排列。
大端:高位字节存低地址
小端:低位字节存低地址
例如 32 位数 `0x12345678`:
| 地址递增方向 | 大端 | 小端 |
| 低地址 -> 高地址 | 12 34 56 78 | 78 56 34 12 |
2.对齐方式
对齐是指多字节数据最好放在其大小的整数倍地址上。
例如:
- 32 位字放在 4 的倍数地址;
- 16 位半字放在 2 的倍数地址。

对齐好处:
- 硬件访问简单;
- 性能更高;
- 避免某些体系结构异常。
如果只想读一个字符,不能用普通 `LDR` 读整个字,而应使用:
LDRB r0, [r1]
如果读 16 位半字:
LDRH r0, [r1]
加载到 32 位寄存器时,高位如何处理取决于指令是否带符号扩展。
小端拼接
本页通常讲如何把多个字节拼成半字或字。
小端中低地址字节是低有效字节。
若:
Memory[p] = low byte
Memory[p+1] = high byte
拼接:
LDRB r0, [r2,#0]
LDRB r1, [r2,#1]
ORR r0, r0, r1, LSL #8
大端拼接
大端中低地址字节是高有效字节。
因此拼接顺序与小端相反。
统一规律:
> 端格式决定哪个地址上的字节放在结果的高位,哪个放在低位。
如果地址不是 4 的倍数,直接 `LDR` 可能:
- 硬件不支持;
- 产生异常;
- 自动修正但性能下降;
- 读到经过旋转或拼接的数据。
更通用的做法是:
- 先读包含目标数据的两个对齐字;
- 根据偏移拼接出目标 32 位数据。
3.按字节拼接数据
思想:
找到对齐地址
读取相邻字
计算字节偏移
移位
OR 拼接
这和网络报文、文件格式解析非常像:硬件读出的字节需要软件重新组合。
读取无符号半字并拼接:
本页给出通过两次字节访问读取无符号半字的代码。
小端示例:
LDRB r0, [r2,#0]
LDRB r1, [r2,#1]
ORR r0, r0, r1, LSL #8
含义:
- 第一个字节放低 8 位;
- 第二个字节左移 8 位放高 8 位;
- `ORR` 合成 16 位结果。
4.任意对齐地址加载 32 位字

本页讲更复杂的未对齐 32 位字加载。

典型步骤:
BIC r2, r0, #3
LDMIA r2, {r1,r3}(块移动下节讲,也就是一起入栈)
AND r2, r0, #3
MOVS r2, r2, LSL #3
解释:
- `BIC r2,r0,#3` 清除低两位,得到 4 字节对齐地址;
- `LDMIA` 读取两个相邻字;
- `AND` 得到原地址在字内的字节偏移;
- 左移把字节偏移换成位偏移;
- 通过移位和 OR 拼接目标字。
也就是说先找到起始位置BIC把低两位清0,这个是固定操作,然后后面AND和MOVS和MOVNE这三个指令会计算出他的偏移位置,也就是说比方说这个题上面的图要计算字节偏移,之后转换到位偏移,之后把高32和低32位的r3和r1移位合并

