ARM中的对齐问题
非对齐数据访问
ARM体系中存储系统非对齐的存储访问操作A RM系列处理器是RISC (Reducded Instruction Set Computing)处理器。
很多基于ARM的高效代码的程序设计策略都源于RISC处理器。
和很多RISC处理器一样,ARM系列处理器的内存访问,也要求数据对齐,即存取“字(Word)”数据时要求四字节对齐,地址的bits[1:0]==0b00;存取“半字(Halfwords)”时要求两字节对齐,地址的bit[0]==0b0;存取“字节(Byte)”数据时要求该数据按其自然尺寸边界(Natural Size Boundary)定位。
ARM编译程序通常将全局变量对齐到自然尺寸边界上,以便通过使用LDR和STR指令有效地存取这些变量。
这种内存访问方式与多数CISC (Complex Instruction Set Computing)体系结构不同,在CISC体系结构下,指令直接存取未对齐的数据。
因而,当需要将代码从CISC体系结构向ARM处理器移植时,内存访问的地址对齐问题必须予以注意。
在RISC体系结构下,存取未对齐数据无论在代码尺寸或是程序执行效率上,都将付出非常大的代价。
本文将从以下几个方面讨论在ARM体系结构下的程序设计问题。
未对齐的数据指针C和C++编程标准规定,指向某一数据类型的指针,必须和该类型的数据地址对齐方式一致,所以ARM编译器期望程序中的C指针指向存储器中字对齐地址,因为这可使编译器生成更高效的代码。
比如,如果定义一个指向int数据类型的指针,用该指针读取一个字,ARM 编译器将使用LDR指令来完成此操作。
如果读取的地址为四的倍数(即在一个字的边界)即能正确读取。
但是,如果该地址不是四的倍数,那么,一条LDR 指令返回一个循环移位结果,而不是执行真正的未对齐字载入。
循环移位结果取决于该地址向对于字的边界的偏移量和系统所使用的端序(Endianness)。
例如,如果代码要求从指针指向的地址0x8006载入数据,即要载入0x8006、0x8007、0x8008和0x8009四字节的内容。
ARM的七种异常类型
ARM7支持六种操作模式:(1)用户模式(usr):正常的程序执行状态(2)FIQ模式(fiq):支持数据传送或通道处理(3)IRQ模式(irq):用于通用的中断处理(4)管理模式(svc):用于操作系统的保护模式(5)异常模式(abt):数据或者指令预取异常时进入(6)无定义模式(und):当无定义指令被执行时进入(7)软件控制,外部中断,异常处理都可以改变操作模式。
大部分的应用程序在用户模式下执行。
其他模式,比如管理模式,在中断、异常服务、或者访问被保护资源时进入。
ARM 的中央寄存器集是16 个用户寄存器R0 – R15。
这些寄存器均是32 位宽度,R0 – R12 没有其他特殊功能,寄存器R13 – R15在CPU中有特殊功能。
R13被用作栈指针(stack pointer,SP)。
R14被称为链接寄存器(link register, LR),当调用一个函数时返回地址被自动保存到链接寄存器,在函数返回时有效。
这使得快速进入和返回“叶”函数(不调用其他函数的函数)成为可能。
如果函数是分支的一部分(即该函数将调用另一个函数),链接寄存器必须入栈(R13)。
R15 是程序计数器(program counter, PC)。
有趣的是,许多指令也可以在R13 – R15中执行,就像它们是标准的用户寄存器。
ARM中断的问题ARM的七种异常类型---------1> 复位异常2> 数据访问中止异常3> 快速中断请求异常4> 一般中断请求5> 预取指令异常6> 软件中断异常7> 未定义异常-------------------------问题:1> 为什么除了进入复位异常模式外,在别的异常处理模式中都允许FIQ中断?2> 数据访问中止异常的优先级大于 FIQ异常,为什么在数据访问异常处理模式中,还允许 FIQ中断?这样不就成了:在高优先级异常处理中允许低优先级的中断发生?即使这样,因为FIQ中断的优先级 < 数据异常中断优先级,也不会进入 FIQ中断处理程序啊,这样不就更没有用处了??ARM体系的各种异常的分析(学习日记)- [ARM7TDMI]版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明/logs/10669519.html1.复位异常(1)当内核的nRESET信号被拉低时,ARM处理器放弃正在执行的指令,当nRESET信号再次变高时,ARM处理器进行复位操作;(2)系统复位后,进入管理模式对系统进行初始化,复位后,只有PC(0x00000000)和CPSR (nzcvqIFt_SVC)的值是固定的,另外寄存器的值是随机的。
ARM处理器下的内存对齐问题
ARM处理器下的内存对齐问题介绍内存访问可以分为aligned和未对齐unaligned.对齐内存访问发生在数据分配在natural size boundary,如果这个数据的大小是4 bytes,而且它分配的地址可以被4整除,它就是分配在natural size boundary的,它就是内存对齐的.未对齐内存访问就是其他的所有情况(内存地址不能被4整除);ARM处理器被设计成可以高效的访问对齐数据,在ARM处理器上尝试访问未对齐内存数据将得到两种结果:错误数据或显著的执行差异(很快会讨论这些不同的表现).这不同于其他的CISC类型的处理器,它们可以正常的访问未对齐数据.这篇文档将会描述一些对应用程序来说通用的方式处理未对齐内存访问和提供一些推荐的解决方案以解决这些问题.症状上述问题针对所有ARM架构的.然而,根据MMU是否使能和操作系统的支持,应用程序在不同的平台上有不同的表现.在默认情况下,未对齐内存访问不会被捕捉,而是返回一个错误数据.在使能了MMU的平台上,OS将可以捕捉未对齐内存访问而且在运行时调整正确.返回的结果将是正确的数据,但是将花费 10-20个cpu周期.通常原因类型分配Code:void my_func(char *a){int *b = (int *)a;DBGPRINTF("%d", *b);}这个简单的例子可以生成未对齐内存访问,因为我们不能保证参数char* a是在4字节边界上的.这样的类型定义在任何时候都应该避免.使用数据buffer大多数常见的未对齐内存访问发生在错误的处理数据buffer,这些数据buffer可能包含任何从usb端口,网路,或文件中读取的数据.通常会设置这些数据为packed,意味着没有padding嵌入以确保buffer中的数据是natural size boundary的.在这个例子中,我们将讨论装载从一个文件一个windows BMP格式数据,然后解析其文件头的情况.一个windows BMP文件包含一个以下数据项的文件头,文件头由两个结构体组成:Code:typedef PACKED struct{unsigned short int type;unsigned int size;unsigned short int reserved1, reserved2;unsigned int offset;} HEADER;typedef PACKED struct{unsigned int size;int width,height;unsigned short int planes;unsigned short int bits;unsigned int compression;unsigned int imagesize;int xresolution,yresolution;unsigned int ncolours;unsigned int importantcolours;} INFOHEADER;注意HEADER和INFOHEADER结构体的大小分别是14和40字节.假设我们想在程序运行是检测图片的宽带和高度,得到这些数据的代码如下:Code:#define INFOHEADER_OFFSET (sizeof(HEADER))#define WIDTH_OFFSET (INFOHEADER_OFFSET + offsetof(INFOHEADER, width))#define HEIGHT_OFFSET (INFOHEADER_OFFSET + offsetof(INFOHEADER, height))int imageWidth, imageHeight;void * fileBuf;pMe->mFile = IFILEMGR_OpenFile(pMe->mFileMgr, "test.bmp", _OFM_READ);if (pMe->mFile){IFILE_GetInfo(pMe->mFile, &fileInfo);fileBuf = MALLOC(fileInfo.dwSize);if (fileBuf){result = IFILE_Read(pMe->mFile, fileBuf, fileInfo.dwSize);if (result == fileInfo.dwSize){imageWidth = *((uint32*)(((byte*)fileBuf) + WIDTH_OFFSET));imageHeight = *((uint32*)(((byte*)fileBuf) + HEIGHT_OFFSET));}}}注意宽度和高度的偏移.因为它们位于一个half-word boundary,以上面的代码访问它们的值将是未对齐内存访问.一些推荐的方式解决这个问题如下:推荐方案使用memcpy我们第一个选择是简单的使用memcpy将数据从buffer处理到我们的局部变量中:Code:if (result == fileInfo.dwSize){MEMCPY(&imageWidth,(((byte*)fileBuf)+WIDTH_OFFSET),sizeof(uint32));MEMCPY(&imageHeight,(((byte*)fileBuf)+HEIGHT_OFFSET),sizeof(uint32));}结果是内存被紧密的拷贝,避免了对齐问题.使用PACKED编译指令或者,我们可以使用PACKED编译指令以允许使用指针直接的访问我们想要的数据.也就是强制编译器处理对齐问题.在BREW环境下,PACKED定义如下:Code:#ifdef __ARMCC_VERSION#define PACKED __packed#else#define PACKED#endif通过标明一个指针是PACKED的,ARM编译器将始终生成合适的指令可以正确的访问内存.不管对齐,上边的例子的一个修改的版本,使用PACKED的指针,如下:Code:#define INFOHEADER_OFFSET (sizeof(HEADER))#define WIDTH_OFFSET (INFOHEADER_OFFSET + offsetof(INFOHEADER, width))#define HEIGHT_OFFSET (INFOHEADER_OFFSET + offsetof(INFOHEADER, height))PACKED uint32 * pImageWidth;PACKED uint32 * pImageHeight;uint32 imageWidth, imageHeight;void * fileBuf;pMe->mFile = IFILEMGR_OpenFile(pMe->mFileMgr, "test.bmp", _OFM_READ);if (pMe->mFile){IFILE_GetInfo(pMe->mFile, &fileInfo);fileBuf = MALLOC(fileInfo.dwSize);if (fileBuf){result = IFILE_Read(pMe->mFile, fileBuf, fileInfo.dwSize);if (result == fileInfo.dwSize){pImageWidth = (uint32*)(((byte*)fileBuf) + WIDTH_OFFSET);pImageHeight = (uint32*)(((byte*)fileBuf) + HEIGHT_OFFSET);imageWidth = *pImageWidth;imageHeight = *pImageHeight;}}}定义Well-Aligned数据结构虽然我们一般不能控制定制的数据格式,比如上面例子中的BMP文件头,但是,当我们定义自己的数据结构我们可以将数据设计成Well-Aligned方式.以下例子演示这种方式:Code:#ifdef __ARMCC_VERSIONtypedef PACKED struct{short a; // offsetof(a) = 0int b; // offsetof(b) = 2 ?misalignment problem!short c; // offsetof(c) = 6} BAD_STRUCT;typedef struct{int b; // offsetof(b) = 0 ?no problem!short a; // offsetof(a) = 4short c; // offsetof(c) = 6} GOOD_STRUCT;简单的重新定义结构提成员的顺序,我们可以解决一些对齐问题.同时注意如果BAD_STRUCT没有定义为PACKED,编译器一般将会插入padding以使每个成员是Well-Aligned的.然而,这通常是不可取的,因为它浪费内存,而且几乎总是可以通过按顺序声明减少大小而避免。
gcc arm cache aligned 参数
gcc arm cache aligned 参数
在GCC中,可以使用特定的参数来控制生成的代码对ARM架构的缓存对齐要求。
这主要涉及数据结构的对齐,以便更有效地利用硬件特性,例如减少内存访问延迟和提高数据存取速度。
在GCC中,你可以使用aligned属性来指定一个变量或结构体应该对齐到特定的地址边界。
例如,要指定一个变量对齐到16字节边界,你可以这样做:
c
int __attribute__((aligned(16))) my_variable;
对于结构体,你可以这样指定:
c
struct __attribute__((aligned(16))) MyStruct {
int field1;
double field2;
// 其他字段...
};
这样,GCC将会生成代码以确保my_variable和MyStruct的实例对齐到指定的地址边界。
对于缓存对齐,你需要确保你的数据结构对齐到缓存的边界,通常是缓存行的大小。
这有助于提高数据访问的速度并减少缓存未命中(cache misses)的可能性。
请注意,具体的缓存行大小取决于具体的ARM架构和处理器实现。
你需要查阅相关的ARM架构文档或处理器手册以获取准确的缓存行大小信息。
此外,你还可以使用GCC的-malign-double和-malign-double-armv8选项来强制对齐双精度浮点数和ARMv8双精度浮点数。
这些选项可以影响编译器生成的代码,以确保双精度浮点数对齐到适当的地址边界。
cortex-m3栈的8字节对齐
cortex-m3栈的8字节对齐⼀、什么是栈对齐?栈的字节对齐,实际是指栈顶指针须是某字节的整数倍。
因此下边对系统栈与MSP,任务栈与PSP,栈对齐与SP对齐这三对概念不做区分。
另外下⽂提到编译器的时候,实际上是对编译器汇编器连接器的统称。
之前对栈的8字节对齐理解的不透,就在⽹上查了好多有关栈字节对齐、还有⼀些ARM对齐伪指令的资料信息,⼜做了⼀些实验,把这些零碎的信息拼接在⼀起,总觉得理解透这个问题的话得长篇⼤论了。
结果昨天看了AAPCS⼿册、然后查到了没有使⽤PRESERVE8伪指令出现错误的实例,突然觉得长篇⼤论不存在了,半篇⼩论这问题就能理顺了。
⼆、AAPCS栈使⽤规约在ARM上编程,但凡涉及到调⽤,就需要遵循⼀套规约AAPCS:《Procedure Call Standard for the ARM Architecture》。
这套规约⾥⾯对栈使⽤的约定如下:5.2.1.1Universal stack constraintsAt all times the following basic constraints must hold:Stack-limit < SP <= stack-base. The stack pointer must lie within the extent of the stack.SP mod 4 = 0. The stack must at all times be aligned to a word boundary.A process may only access (for reading or writing) the closed interval of the entire stack delimited by [SP, stack-base – 1](where SP is the value of register r13).NoteThis implies that instructions of the following form can fail to satisfy the stack discipline constraints, even when reg points within the extent of the stack.ldmxx reg, {..., sp, ...} // reg != spIf execution of the instruction is interrupted after sp has been loaded, the stack extent will not be restored, so restarting theinstruction might violate the third constraint.5.2.1.2Stack constraints at a public interfaceThe stack must also conform to the following constraint at a public interface:SP mod 8 = 0. The stack must be double-word aligned.可以看到,规约规定,栈任何时候都得4字节对齐,在调⽤⼊⼝得8字节对齐。
ARM平台的地址对齐问题
ARM平台的地址对齐问题前言ARM流行已久,做嵌入式开发的不知道ARM不大可能。
鉴于其所具备的较低功耗下的较高性能,也就成了大多数嵌入式设备的首选了。
不过对于刚上手的人来说,有可能会遇到一些稀奇古怪的问题。
毕竟大部分人都习惯了IA-32下的程序设计,虽然两者都是32位的处理器,但是体系架构完全不同,于是也导致了一些隐含的问题。
这里想描述一下一个有点蛊惑的问题,即在ARM上访问非对齐地址内容,会出现所谓“不可预料”结果的问题。
ARM内存访问的对齐问题按照ARM 文档上的描述,其访问规则如下: 1. 一次访问4字节内容,该内容的起始地址必须是4字节对齐的位置上; 2. 一次访问2字节内容,该内容的起始地址必须是2字节对齐的位置上;(单字节的没有这个问题,就不用考虑啦。
)好,既然规则如此,那应该遵守。
不过么,不安分的人往往喜欢破坏规则,喜欢看看不遵守规则会有什么结果;另外么,即便遵规蹈距的人,有时也难免考虑不周,犯个错也是正常现象。
好,那么让我们来看看犯错的结果吧。
例如下面的代码:char buff[8] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xab, 0xbc, 0xcd};int v32, *p32;short v16, *p16;p32 = (int*)&( buff[1] ); //unalignment p16 = (short*)&( buff[1] ); //unalignment v32 = *p32; //what’s the result? v16 = *p16; //what’s the result? 如果上面这段代码在IA-32上运行,那么结果应该如下: v32 = 0x9a785634 v16 = 0x5634 即便非对齐地址上访问,IA-32也就是牺牲一点性能,但是结果保证是正确的。
恩,这也是我们所期望的…… 可是…… 换到ARM上呢?我们来看看在ADS1.2编译后,执行的结果如下: v32 = 0x12785634 v16 = 0x1234 这个结果有点奇怪了吧。
arm字节对齐
arm中的字节对齐问题(2011-04-02 11:03:56)转载标签:杂谈昨天调程序,发现一个不得解的问题,传过来的地址明明是正确的,可是一读却是一条非法指令。
不写操作。
很长时间不能解决,师兄过来看了一下,才现是字节对齐的问题。
唉,终于碰到对齐问题了,那就好好解决一下吧。
先说下我遇到的问题typedef sturct{char a;char b;char c[255];} FS;FS fs;....disk_read(...,fs->c,...)....void disk_read(...,int* p,...){....*p++=0x01010101; //error:....}到了这一步,也就可以看一下问题发生的原因了,在结构体中,对将c做到字节对齐,这样和disk_read中的P的四字节对齐是不同的,这样写的时候由于不是四字节对齐,就会出错下面转两篇字节对齐的文章。
戒之戒之=====================================================有了上面的基础后,在一些数据结构中就要消除这些字节带来的影响,特别是在文件访问的过程中,在各个平台上都会遇到。
文件为了保持最小,利用空间的原则,会按照字节来存储的,但是我们在内存中定义的结构会按最优原则使效率最大,这样会保持边界对齐。
那么如何消除影响呢,先看在 vc中如保操作#pragma pack(push, 1) == #paragma pack(push) #paragma pack(1) struct T{int a;char b;}#paragma pack(pop)再来看看ads 在arm平台是如何操作的__packedstruct T{int a;char b;}最后来看看gcc下面的操作__attribute__((__packed__))struct T{int a;char b;}最后,让我们来看看怎么定义一个结构才是移植性够好的结构PACK_STRUCT_BEGINstruct ip_hdr {PACK_STRUCT_FIELD(u16_t _id);PACK_STRUCT_FIELD(struct ip_addr src);} PACK_STRUCT_STRUCT;PACK_STRUCT_END通过引个宏来改变这些相应的结构#ifdef __GNU_C__#define PACK_STRUCT_FIELD(x) x#define PACK_STRUCT_STRUCT __attribute__((__packed__))#define PACK_STRUCT_BEGIN#define PACK_STRUCT_END#elif__ADS__#define PACK_STRUCT_FIELD(x) __packed x#define PACK_STRUCT_STRUCT#define PACK_STRUCT_BEGIN __packed#define PACK_STRUCT_END#elif __VC__#define PACK_STRUCT_FIELD(x) x#define PACK_STRUCT_STRUCT#define PACK_STRUCT_BEGIN #pargma pack (push, 1) (问题代码) #define PACK_STRUCT_END #pargma pack (pop) (问题代码)#else#define PACK_STRUCT_FIELD(x)#define PACK_STRUCT_STRUCT#define PACK_STRUCT_BEGIN#define PACK_STRUCT_END#endif好啦,到此为止一切都结束了,这就是相关的字节对齐的一些操作,原来我只以为只有最后这一种情况才是呢,最上面的那种情况是后来调试才遇到的,至于以后,可能还会有,再做补充了ps:上面有两行问题代码,自己用的时候才发现,宏定义中出现"#",几乎不可能,所以放弃这样的想法宏定义中的#可以把一个数字变成字串 ##则代表字符串连接。
arm32位的cpu对齐方式
arm32位的cpu对齐方式
ARM 32位CPU的对齐方式是指数据在内存中的存储位置。
对齐
是指数据在内存中的起始地址是否符合一定的规则。
ARM架构中,
数据对齐通常指的是按照数据的大小将数据存储在内存中的起始地址,以提高数据访问的效率和性能。
在ARM 32位架构中,数据对齐通常遵循以下规则:
1. 字节对齐,8位数据的起始地址可以是任意地址;16位数据
的起始地址必须是2的倍数;32位数据的起始地址必须是4的倍数。
2. 半字对齐,16位数据的起始地址必须是2的倍数;32位数
据的起始地址必须是4的倍数。
3. 字对齐,32位数据的起始地址必须是4的倍数。
对齐的好处在于可以提高内存访问的速度,因为处理器可以更
快地访问对齐数据。
如果数据没有按照规定的对齐方式存储,处理
器可能需要多次访问内存,降低了访问效率,甚至可能导致错误或
异常。
总的来说,ARM 32位CPU的对齐方式是按照数据的大小将数据存储在内存中的起始地址,以提高数据访问的效率和性能。
这种对齐方式是为了充分利用处理器的特性,提高数据访问的效率。
ARM单选习题库及答案
ARM单选习题库及答案一、单选题(共100题,每题1分,共100分)1、下面与嵌入式处理器有关的叙述中,错误的是:A、嵌入式处理器只有在供电的情况下才有可能正常工作B、嵌入式处理器本身就是一个嵌入式最小硬件系统C、嵌入式处理器工作时需要时钟信号正确答案:B2、()显示屏是利用有机电致发光二极管制成的显示屏。
本设计选用0.96寸OLED12864显示屏作为系统的显示设备。
A、OLEDB、ABCDC、EFGH正确答案:A3、下面哪种操作系统最方便移植到嵌入式设备中A、WindowsB、linuxC、unix正确答案:B4、Systick定时器的位数是()位。
A、24B、16C、32正确答案:A5、ADD R0,R1,#3属于()寻址方式A、立即寻址B、多寄存器寻址C、寄存器直接寻址正确答案:A6、关于STM32芯片内部中的五个时钟源,说法正确的是()?A、其它选项都是对的B、HSI是高速内部时钟,RC振荡器,频率为8MHzC、LSI是低速内部时钟,RC振荡器,频率为40kHz正确答案:A7、下列是高速内部时钟的是()。
A、HSEB、LSIC、HSI正确答案:C8、嵌入式系统是以()为核心,以计算机技术为基础,软硬件可裁剪,适应应用系统对功能、可靠性、安全性、成本、体积、重量、功耗、环境等方面有严格要求的专用计算机系统。
A、应用B、计算机技术C、嵌入式正确答案:A9、STM32芯片最高工作频率是()?A、68MHzB、72MHzC、24Mhz正确答案:B10、开发板的主CPU和仿真器CPU都采用()作为时钟信号发生器A、外拉晶振B、HSEC、PLL正确答案:A11、GPIO_Speed用以设置选中管脚的速率,则GPIO_Speed_50MHz设置管脚的最高输出速率为()MHzA、2B、50C、20正确答案:B12、中断控制器中有多少个()DMA控制器A、4B、2C、3正确答案:A13、温度传感器DS18B20和红外接收头均为()A、单总线传感器B、双总线传感器C、总线传感器正确答案:A14、操作电压的叙述错误的是()A、I/O:2.2VB、I/O:3.3VC、I/O:6.6V正确答案:B15、()通信是指使用一条数据线,将数据一位一位地在这条数据线上依次传输。
arm align用法
arm align用法【原创版】目录1.ARM 指令集介绍2.arm align 指令的作用3.arm align 指令的语法格式4.arm align 指令的例子5.arm align 指令的优势与应用场景正文1.ARM 指令集介绍ARM(Advanced RISC Machine)指令集,即高级 RISC 机器指令集,是一种基于 RISC(精简指令集计算机)架构的指令集。
相较于 CISC(复杂指令集计算机)架构,RISC 架构的指令集具有指令简单、执行速度快等特点。
ARM 指令集广泛应用于嵌入式系统、移动设备、服务器等领域。
2.arm align 指令的作用在 ARM 指令集中,arm align 指令用于对齐内存地址。
对齐内存地址在数据访问和指令执行过程中具有重要意义,可以提高数据访问速度和指令执行效率。
通过使用 arm align 指令,可以确保数据访问或指令执行时,内存地址与其数据类型对齐。
3.arm align 指令的语法格式arm align 指令的语法格式如下:```align [optional padding]```其中,optional padding 表示可选的填充字段。
align 后面可以跟一个表示对齐大小的数字,单位为字节。
当不指定对齐大小时,默认为 4 字节对齐。
4.arm align 指令的例子下面是一个 arm align 指令的例子:```LDR PC, [PC, #-4]ADD PC, PC, #4```在这个例子中,首先使用 LDR 指令将 PC 寄存器的值加载到 [PC, #-4] 的内存地址处。
接着,使用 ADD 指令将 PC 寄存器的值与 4 相加,并将结果存储回 PC 寄存器。
通过 arm align 指令,可以确保 PC 寄存器的值在 4 字节的边界上,从而提高指令执行效率。
5.arm align 指令的优势与应用场景arm align 指令的优势在于可以提高数据访问速度和指令执行效率。
arm align用法
ARM Align用法1. 什么是ARM Align?ARM Align是一种用于对齐内存访问的技术,它可以提高内存访问的效率和性能。
在ARM体系结构中,内存访问通常是按照字节对齐的,即每次访问一个字节。
但是,对于某些特殊的数据结构,如数组或结构体,字节对齐可能会导致额外的开销和性能损失。
ARM Align可以通过对内存地址进行对齐操作,使得内存访问更加高效。
2. ARM Align的原理ARM Align的原理主要包括两个方面:对齐规则和对齐操作。
2.1 对齐规则ARM Align的对齐规则是指数据在内存中的存储地址必须是某个特定值的倍数。
在ARM体系结构中,对齐规则通常是按照数据类型的大小来确定的。
例如,对于一个32位整数,它的对齐规则是4字节对齐,即存储地址必须是4的倍数;对于一个64位双精度浮点数,它的对齐规则是8字节对齐,即存储地址必须是8的倍数。
2.2 对齐操作ARM Align的对齐操作是指通过对内存地址进行调整,使得数据按照对齐规则存储。
对齐操作可以分为两种情况:自动对齐和手动对齐。
2.2.1 自动对齐在ARM体系结构中,对于大多数数据类型,编译器会自动进行对齐操作。
例如,当我们声明一个数组或结构体时,编译器会自动为其分配对齐的内存地址。
这种自动对齐操作可以提高内存访问的效率和性能。
2.2.2 手动对齐有时候,我们可能需要手动对齐某些特殊的数据结构,以进一步优化内存访问。
手动对齐可以通过使用特殊的对齐指令来实现。
在ARM体系结构中,常用的对齐指令有PUSH和PULL。
PUSH指令将数据从寄存器压入栈中,并保持对齐;PULL指令将数据从栈中弹出到寄存器,并保持对齐。
3. ARM Align的优势ARM Align的使用可以带来以下几个优势:3.1 提高内存访问效率通过对内存地址进行对齐操作,ARM Align可以减少内存访问的次数,从而提高内存访问的效率。
当数据按照对齐规则存储时,CPU可以一次读取或写入多个字节,减少了访问内存的次数,从而提高了程序的执行速度。
关于arm汇编中的align
关于arm汇编中的align经常会看到arm-linux汇编中有如下的指令:.align n它的含义就是使得下面的代码按一定规则对齐,.align n 指令的对齐值有两种方案,n 或2^n ,各种平台最初的汇编器一般都不是gas,采取方案1或2的都很多,gas的目标是取代原来的汇编器,必然要保持和原来汇编器的兼容,因此在gas中如何解释 .align指令会显得有些混乱,原因在于保持兼容。
arm-linu是按照2^n的方案对齐的,需要说明的是这个对齐和ld-script里的对齐不同,不是一会事。
下面的英文就不同平台的对齐进行了说明:版本2.11.92.0.12的gas的info(Mandrake 8.2上的)这样说:The way the required alignment is specified varies from system to system. For the a29k, hppa, m68k, m88k, w65, sparc, and Hitachi SH, and i386 using ELF format, the first expression is the alignment request in bytes. For example `.align 8' advances the location counter until it is a multiple of 8. If the location counter is already a multiple of 8, no change is needed.For other systems, including the i386 using a.out format, and the arm and strongarm, it is the number of low-order zero bits the location counter must have after advancement. For example `.align 3' advances the location counter until it a multiple of 8. If the location counter is already a multiple of 8, no change is needed.从这段文字来看,ARM的.align 5就是2的5次方对齐,也就是4字节对齐,通过反汇编也可以看出对齐方式:.align 5stmfd sp!, {r0 - r3, lr}mov r0, ipldmfd sp!, {r0 - r3, pc}^.align 5stmfd sp!, {r0 - r3, lr}mov r0, ipmov ip, r0ldmfd sp!, {r0 - r3, pc}^反汇编:00000000 <.text>:0: e92d400f stmdb sp!, {r0, r1, r2, r3, lr}4: e1a0000c mov r0, ip8: e8fd800f ldmia sp!, {r0, r1, r2, r3, pc}^...20: e92d400f stmdb sp!, {r0, r1, r2, r3, lr}24: e1a0000c mov r0, ip28: e1a0c000 mov ip, r02c: e8fd800f ldmia sp!, {r0, r1, r2, r3, pc}^30: e1a00000 nop (mov r0,r0)34: e1a00000 nop (mov r0,r0)38: e1a00000 nop (mov r0,r0)3c: e1a00000 nop (mov r0,r0)一些忠告:In the future, everytime when you build an elf file, you need meantime created your map file. And then you will avoid mistakes like th is align.Also, please also pick up some linker script knowlege part. For embedded system, we frequently play the linker script to tune an image, for example, align some special section and so on for protection or/and cache purpose. wish helpful。
中北大学嵌入式习题答案第2章
第二章 ARM体系结构一、填空1、 ARM微处理器支持7种运行模式为、、、、、、。
用户模式(usr): ARM处理器正常的程序执行状态快速中断模式(fiq):用于高速数据传输或通道处理外部中断模式(irq):用于通用的中断处理管理模式(svc):操作系统使用的保护模式数据访问终止模式(abt):当数据或指令预取终止时进入该模式,可用于虚拟存储与存储保护。
系统模式(sys):运行具有特权的操作系统任务。
未定义指令中止模式(und:当未定义的指令执行时进入该模式,可用于支持硬件协处理器的软件仿真。
2、嵌入式微处理器的体系结构可以采用或结构,指令系统可以选和。
冯·诺依曼体系结构:程序和数据共用一个存储空间,程序指令存储地址和数据存储地址指向同一个存储器的不同物理位置,采用单一的地址与数据总线,程序和数据的宽度相同。
例如:8086、ARM7、MIPS…哈佛体系结构:程序和数据是两个相互独立的存储器,每个存储器独立编址、独立访问,是一种将程序存储和数据存储分开的存储器结构。
例如:AVR、ARM9、ARM10…精简指令系统 RISC复杂指令集系统 CISC3、AMBA定义了3组总线、和。
AHB(AMBA高性能总线):用于高性能。
高数据吞吐部件,如CPU、DMA、DSP之间的连接。
ASB(AMBA系统总线):用来作处理器与外设之间的互连,将被AHB取代。
APB(AMBA外设总线):为系统的低速外部设备提供低功耗的简易互连。
系统总线和外设总线之间的桥接器提供AHB/ASB部件与APB部件之间的访问代理与缓冲。
4、ARM系列微处理器支持的边界对齐格式有:、和字对齐。
字节对齐半字对齐5、RS-232C的帧格式由四部分组成,包括:起始位、、奇偶校验位和。
数据位停止位6、ARM微处理器有种工作模式,它们分为两类、。
其中用户模式属于。
七非特权模式特权模式非特权模式7、ARM7TDMI采用级流水线结构,ARM920TDMI采用级流水线。
非对齐数据访问
ARM体系中存储系统非对齐的存储访问操作A RM系列处理器是RISC (Reducded Instruction Set Computing)处理器。
很多基于ARM的高效代码的程序设计策略都源于RISC处理器。
和很多RISC处理器一样,ARM系列处理器的内存访问,也要求数据对齐,即存取“字(Word)”数据时要求四字节对齐,地址的bits[1:0]==0b00;存取“半字(Halfwords)”时要求两字节对齐,地址的bit[0]==0b0;存取“字节(Byte)”数据时要求该数据按其自然尺寸边界(Natural Size Boundary)定位。
ARM编译程序通常将全局变量对齐到自然尺寸边界上,以便通过使用LDR和STR指令有效地存取这些变量。
这种内存访问方式与多数CISC (Complex Instruction Set Computing)体系结构不同,在CISC体系结构下,指令直接存取未对齐的数据。
因而,当需要将代码从CISC体系结构向ARM处理器移植时,内存访问的地址对齐问题必须予以注意。
在RISC体系结构下,存取未对齐数据无论在代码尺寸或是程序执行效率上,都将付出非常大的代价。
本文将从以下几个方面讨论在ARM体系结构下的程序设计问题。
未对齐的数据指针C和C++编程标准规定,指向某一数据类型的指针,必须和该类型的数据地址对齐方式一致,所以ARM编译器期望程序中的C指针指向存储器中字对齐地址,因为这可使编译器生成更高效的代码。
比如,如果定义一个指向int数据类型的指针,用该指针读取一个字,ARM 编译器将使用LDR指令来完成此操作。
如果读取的地址为四的倍数(即在一个字的边界)即能正确读取。
但是,如果该地址不是四的倍数,那么,一条LDR 指令返回一个循环移位结果,而不是执行真正的未对齐字载入。
循环移位结果取决于该地址向对于字的边界的偏移量和系统所使用的端序(Endianness)。
例如,如果代码要求从指针指向的地址0x8006载入数据,即要载入0x8006、0x8007、0x8008和0x8009四字节的内容。
Arm结构体gcc内存边界对齐问题
Arm结构体gcc内存边界对齐问题这段时间移植公司的linux i386程序到Arm linux平台,本以为是件工作量很小的事情,以为只要改几个驱动程序就OK了,没想到在应用程序这一块卡了很长时间。
其中最烦的事情就莫过于结构体内存边界对齐了。
搞了这么久,终于终结了一些小经验。
默认情况下,在32位cpu里,gcc对于结构体的对齐方式是按照四个字节来对齐的。
看以下结构体typedef struct pack{char a;int b;short c;}pack;对于Pack结构体,默认情况下在arm/386平台下(别的平台没试过)sizeof(pack)=12,求解过程如下:sizeof(char)=1;下一个int b,由于是四个字节,要求b的开始地址从32的整数倍开始,故需要在a后面填充3个没用的字节,记为dump(3),sizeof(b)=4,此时相当于结构体扩充为char a;char dump(3);int b;看short c,现在c的前面有8个字节,c是两个字节,c的开始地址是从16的整数开始,在b前面不需再加东西.此时对于结构体来说,sizeof(pack)=10,但是这不是最终结果,最后总的字节数也要能被4个字节整除,所以还需在short c后面再加dump(2);故总的字节数为12.当然以上说的只是简单的情况,下面谈谈Arm,x86在gcc里关于内存边界字节对齐的区别.对于同样的结构体,在386下#prama pack(1)后,sizeof(pack)=1 4 2=7而在arm下同样的操作sizeof(pack)=1 4 2 1=8,即虽然b根a之间不要填充但总的长度必须要是4的整数倍.在ARM 下要使结构体按指定字节对齐,可行的方法1.在makefile里加-fpack-struct 选项,这样的话对所有的结构按一字节对齐.不得不说,确实有那么些质量较差的程序可能需要你部分自然对齐,部分一字节对齐,此时2. typedef struct pack{}__attribute__((packed))可利用__attribute__属性当然最后的方式,还是自己去看ARM体系结构与gcc编译选项了。
ARM考试模拟题+参考答案
ARM考试模拟题+参考答案一、判断题(共100题,每题1分,共100分)1.STM32开发板的备用电源为纽扣电池A、正确B、错误正确答案:A2.GPIO_SesetBits用来给指定端口位设置高电平A、正确B、错误正确答案:A3.基于库函数的开发方式具有容易学习,便于阅读,维护成本低等有点A、正确B、错误正确答案:A4.对于STM32开发板而言,它需要两个晶振,一个是系统主晶振,频率为8MHz,一个是实时时钟晶振,频率为32.768KHz。
A、正确B、错误正确答案:A5.嵌入式系统不适用于环境工程、pos网络等领域。
A、正确B、错误正确答案:B6.GPIO_Mode_IPD表示下拉输出A、正确B、错误正确答案:A7.使能时钟工作步骤是: 1、配置CPU主时钟的来源,以及主时钟的具体频率。
2、配置各部件时钟的具体频率,并打开各部件时钟。
A、正确B、错误正确答案:A8.单片机也称微控制器A、正确B、错误正确答案:B9.S3C2410X有24个外部中断源A、正确B、错误正确答案:A10.在嵌入式系统设计中可以通过ADC来测量电池电压A、正确B、错误正确答案:A11.SRAM用于高速缓存A、正确B、错误正确答案:A12.STM32单片机高电平复位,电路其可以实现上电复位和按键复位。
A、正确B、错误正确答案:B13.按键输入需要配置GPIO工作于输入状态。
A、正确正确答案:AART初始化函数包括USART_SetSpeed。
A、正确B、错误正确答案:B15.高抢占式优先级的中断事件会打断当前的主程序/中断程序运行,俗称嵌套。
A、正确B、错误正确答案:B16.嵌入式不具备高功耗的特点A、正确B、错误正确答案:A17.蓝桥杯ARM嵌入式开发板采用8MHz外接晶振A、正确B、错误正确答案:A18.GPIO_Mode_AF_PP为复用推挽输出A、正确B、错误正确答案:A19.晶振一般叫作晶体谐振器,是一种机电器件A、正确B、错误正确答案:A20.STM32F103ZET6集成了内部温度传感器和实时时钟RTCB、错误正确答案:A21.在每个STM32的芯片上都有两个管脚BOOT0和BOOT1,这两个管脚在芯片复位时的电平状态决定了芯片复位后从哪个区域开始执行程序。
ARM编译器4字节对齐
ARM编译器4字节对齐
(1)我们假设只有⼀个赋初值的char型全局变量,那么系统会在data区分配⼀个4字节的存储空间来存储它。
实际上,只⽤了1个字节,但是为了4字节对齐,只好分配4个字节,所以就会有3个字节浪费。
(2)我们假设在原来基础上增加⼀个赋初值的char型全局变量,那么系统会在data区原来的4字节中取出⼀个字节来保存这个新的变量。
实际上,这时只⽤了2个字节,但是为了4字节对齐,只好分配4个字节,所以就会有2个字节浪费。
(3)我们假设再在原来基础上增加⼀个赋初值的short型全局变量,那么系统会在data区原来的4字节中再取出两个字节来保存这个新的变量。
实际上,这时⽤了4个字节,恰好4字节对齐,所以就不会有浪费。
长期班arm接口随堂试题
ARM 接口试题(时间:1个小时)姓名:【】一、选择题(每空1分,共37分,包括单选和多选,多选、少选均不得分)1.ARM 属于【】[A] RISC 架构[B] CISC架构2.ARM 指令集是【】位宽,Thumb 指令集是【】位宽的。
[A] 8位[B] 16 位[C] 32位[D] 64位3.ARM 指令集是【】字节对齐,Thumb 指令集是【】对齐的[E] 1[F] 2 [G] 3 [H] 44.复位后,ARM处理器处于【】模式,【】状态[A] User[B] SVC [C] System [D] ARM [E] Thumb5.ARM处理器总共【】个寄存器,System模式下使用【】个寄存器,SVC模式下使用【】个寄存器。
[A] 17个[B] 18个[C] 32个[D] 36个[E] 37个6.ARM处理器中优先级别最高的异常为【】,【】异常属于硬件产生的中断[A] FIQ[B] SWI [C] IRQ [D] SVC [E] RESET7.ARM数据处理指令中有效的立即数是【】[A] 0X00AB0000[B] 0X0000FFFF [C ] 0XF000000F [D ] 0X08000012[E] 0X00001F80 [F] 0XFFFFFFFF [G] 0 [H] 0XFF0000008.ATPCS规定中,推荐子函数参数最大为【】个[A] 1[B] 2 [C ] 3 [D ] 49.ATPCS规定中,栈是【】[A] 满加[B] 满减[C ] 空加[D ] 空减10.在用ARM汇编编程是,其寄存器有多个别名,通常PC是指【】,LR 是指【】,SP是指【】[A] R12[B] R13 [C ] R14 [D ] R1511.CPSR寄存器中反映处理器状态的位是【】[A] J位[B] I位[C ] F位[D ] T位12.下面属于ARM 子程序调用指令的是【】[A] B[B] BX [C ] BL [D ] MOV13.ARM7属于【】结构,ARM9属于【】结构。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
ARM中的对齐问题
在ARM 中,当吧一个内存区域初始化为某个结构体时,必须注意字节对
齐情况。
1. 简介
在ARM 中,有ARM 和Thumb 两种指令。
ARM 指令:每执行一条指令,PC 的值加4 个字节(32bits).一次访问4 字节内容,该字节的起始地址必须是4 字节对齐的位置上,
即地址的低两位为bits[0b00],也就是说地址必须是4 的倍数。
Thumb 指令:每执行一条指令,PC 的值加2 个字节(16bits).).一次访问2 字节内容,该字节的起始地址必须是2 字节对齐的位置上,
即地址的低两位为bits=0,也就是说地址必须是2 的倍数。
遵循以上方式叫对齐(aligned)方式,不遵守这样方式称为非对齐(unaligned)的存储访问操作。
ARM CPU 不支持未对齐双字(8 bytes)访问。
双字访问必须是8 字节/4 字节对齐.
2. ARM 平台中的字节对齐关键字
(1) __align(num)
(2) __packed
进行一字节对齐。
(3) __unaligned
用于修饰某个变量,可按照非对齐方式访问。
3. __packed 与#pragma pack(1)的区别
4. __attribute__((aligned))
用于指定类型的最低对齐要求.。