相关阅读
嵌入式https://blog.csdn.net/weixin_45791458/category_12768532.html?spm=1001.2014.3001.5482
本文来源于博主无意之中的一个发现,虽然之前就知道Cortex-M3默认为小端模式,但是偶然发现了一些出乎意料的情况。
首先来看看Arm v7-M指令集架构中相关的定义。
假设存在一个地址A,则该处的规则为:
- 一个地址为A的字,由地址A,A+1,A+2,A+3处的字节组成。
- 一个地址为A的半字,由地址A,A+1处的字节组成。
- 一个地址为A+2的半字,由地址A+2,A+3处的字节组成。
- 一个地址为A的字,由地址A,A+2处的半字组成。
然而,这并未完全指定字(word)、半字(halfword)和字节(byte)之间的映射关系。一个内存系统使用以下映射方案之一。这个选择被称为内存系统的字节序(endianness)。
小端序
在小端字节序的内存系统中,内存中的字节与Arm通用寄存器(32位)之间的映射如图1所示。
图1 小端序映射
在图1中,一个32位的数据的最低字节(即0到7位)保存在地址A处;次低字节(即8到15位)保存在地址A+1处;次高字节(即16到23位)保存在地址A+2处;最高字节(即24到31位)保存在地址A+3处。总结来说就是,高字节存高地址,低字节存低地址。
同时从图2中可以看出,A既是最低字节的地址,也是低半字的地址,还是整个字的地址;A+2既是次高字节的地址,,也是高半字的地址。
图2 字,半字,字节在小端序中的地址
大端序
在大端字节序的内存系统中,内存中的字节与Arm通用寄存器(32位)之间的映射如图3所示。
图3 大端序映射
在图3中,一个32位的数据的最低字节(即0到7位)保存在地址A+3处;次低字节(即8到15位)保存在地址A+2处;次高字节(即16到23位)保存在地址A+1处;最高字节(即24到31位)保存在地址A处。总结来说就是,高字节存低地址,低字节存高地址。
同时从图4中可以看出,A既是最低字节的地址,也是高半字的地址,还是整个字的地址;A+2既是次低字节的地址,也是低半字的地址。
图4 字,半字,字节在大端序中的地址
注意
大端和小端决定了字或半字中字节的解释顺序。举个例子,从地址0x1000读取一个字(4 个字节)将会访问位于内存地址0x1000、0x1001、0x1002 和0x1003的字节,无论使用何种字节序,字节序只决定了如何将这四个字节解释为一个32位的字。
字节序设置仅适用于数据访问,指令获取始终为小端模式。所有对系统控制空间(CSC)的访问都是小端模式。
特殊情况
图5是一条32位的指令,而图6是其对应的存储情况。
图5 MOV指令
图6 指令的存储情况
这似乎有些问题,按照上面的大小端序的定义。从存储情况来说,如果是小端序,这个32位指令应该被解释为0800F04F而不是F04F0800。
这是因为对于Thumb指令而言,要求它们是16位对齐。这意味着一个32位指令被视为两个半字,高半字位hw1,低半字位hw2,但是此时hw1位于较低地址,而hw2位于较低地址,如图7所示,这看起来就像是指令只在半字层面才是小端序。
图7 指令的内存特殊小端序