ARM问题总结

five0918

贡献于2014-07-28

字数:0 关键词: 嵌入式开发

ARM问题总结 1、ARM 指令中 MOV 和 LDR 有什么区别? ARM 是 RISC 结构,数据从内存到 CPU 之间的移动只能通过 L/S 指令来 完成,也就是 ldr/str 指令。比如想把数据从内存中某处读取到寄存器中, 只能使用 ldr。 比如: ldr r0, 0x12345678 就是把0x12345678这个地址中的值存放到r0 中。而 mov不能干这个活, mov 只能在寄存器之间移动数据,或者把立即数移动到寄存器中,这个 和 x86 这种 CISC 架构的芯片区别最大的地方。 2、ARM 的 DCD 指令 在中断向量表中不直接 LDR PC,"异常地址"。而是使用一个标号,然后 再在后面使用 DCD 定义这个标号,其原因是: LDR 指令只能跳到当前 PC 4KB 范围内,而 B 指令能跳转到 32MB 范围, 而现在这样在 LDR PC, "xxxx"这条指令不远处用"xxxx"DCD 定义一个字, 而这个字里面存放最终异常服务程序的地址,这样可以实现 4GB 全范围 跳转。 另:有如下语句 USR_STACK_LEGTH EQU 64 ;定义用户模式堆栈长度为 64 字 StackUsr DCD UsrStackSpace + (USR_STACK_LEGTH-1)*4 ;定义一 个字的空间,这个字的内容是一个递减堆栈的首地址 UsrStackSpace SPACE USR_STACK_LEGTH*4 ;为用户模式分配一 个 64 字的堆栈空间,若这个堆栈做递减使用,则其首地址为 UsrStackSpace + (USR_STACK_LEGTH-1)*4 3、为什么用 R15 做通用寄存器时,地址要加 8 个字节 ARM 采用了流水线机制,当正确读取了 PC 的值时,该值为当前指令地 址值加 8 个字节。也就是说,对于 ARM 指令集来说,PC 指向当前指令 的下两条指令的地址。 由于 ARM 指令是字对齐的,PC 值的第 0 位和第 1 位总为 0。需要注意 的是,当使用指令 STR/STM 保存 R15 时,保存的可能是当前指令地址 值加 8 字节,也可能保存的是当前指令地址加 12 字节。到底是哪种方式, 取决于芯片具体设计方式。 4、ARM 中的协处理器 ARM 的协处理器指令主要用于 ARM 处理器初始化、 ARM 协处理器的 数据处理操作,以及在 ARM 处理器的寄存器和协处理器的寄存器之间传 送数据,和在 ARM 协处理器的寄存器和存储器之间传送数据。 5、 基本 ARM 指令功能段 1、使用 ARM 汇编指令实现 if 条件执行。 如果 if 语句中判断的条件只有一个,用 CMP 和 ARM 的条件执行就可以 实现,如(假设 a 和 b 分别在寄存器 R0、R1 中): C 语言 ARM 汇编语言 if(a>b) a++; else b++; CMP R0,R1 ADDHI R0,R0,#1 ADDLS R1,R1,#1 如果在 if 条件语句中逻辑表达式是多个条件的逻辑组合,则需要用 CMP 配合分支指令实现 if,如(假设 a 和 b 分别在寄存器 R0、R1 中): C 语言 ARM 汇编语言 if((a!=b)&&(b==20)) a=a+b; else a=a-b; CMP R0,#10 BEQ Else CMPNE R1,#20 BNE Else ADD R0,R0,R1 B Exit Else SUB R0,R0,R1 Exit ;其他指令 if((a!=b)||(b==20)) a=a+b; else a=a-b; CMP R0,#10 BNE If CMPEQ R1,#20 BEQ If SUB R0,R0,R1 B Exit If ADD R0,R0,R1 Exit ;其他指令 2、使用 ARM 汇编指令实现 for 循环结构。 使用 for 循环时,首先要初始化,申请局部变量,对应于 ARM 中堆栈的 变化。进入循环体后,先判断条件,不如何则跳出,符合则执行,然后 自增或自减,循环,例如: C 语言 ARM 汇编语言 for(i=0;i<100;i++) { a=a+b; } EOR R0,R0,R0 Loop CMP R0,#100 BHS Exit ADD R1,R1,R2 ADD R0,R0,#1 B Loop Exit ;其他指令 3、使用 ARM 汇编指令实现 while 循环结构。 while 循环结构先判断条件,然后才执行,用 ARM 汇编语言实现就是先 判断条件,不符合则跳转,符合则执行,最后循环,如: C 语言 ARM 汇编语言 while(a=b) { 执行体; } Loop CMP R0,R1 BNE Exit ;执行体 B Loop Exit ;其他指令块 4、使用 ARM 汇编指令实现 do…while 循环结构。 do-while 循环结构先执行,然后判断条件,用 ARM 汇编语言实现即先 执行,然后比较判断条件,不符合条件则退出,符合则循环执行,如: C 语言 ARM 汇编语言 do { 执行体; } while(a=b); Loop ;执行体 CMP R0,R1 BEQ Loop 6、ARM 的字对齐是什么意思? arm 指令因为起始地址是 00 结尾的,所以 pc 的地址一定就是以 00 结尾。 thumb 指令时起始地址末尾是 0 所以 pc 还是零。就这么简单。字对齐是指 32 位处理器以 4 字节(32 位么)为一个单位取指令,如果是 char 型数据(定义 为 2b),但其实在存储中也是占 4B。如果是两个连续的 char 经过编译的优 化可一起占 4B。 7、ARM 的宏定义 格式中的[$ label]的作用 当宏定义体内部跳转时,这个参数会起到至关重要的作用。要想在宏内部跳 转,就必须在宏定义体内部有程序标号如(LOOP),如果不使用参数($ label), 当在一个程序段内调用两次宏的时候,编译器就会出现错误,因为当汇编时 产生了两个相同名字的程序标号。 例子: 宏的定义体: MACRO $PM DELAY $CanShu $PM LDR R7,=$CanShu ; LDR R7,[R7] ; 此时参数是一个立即数 如果是变量的话会用到这 句 $PM.LOOP SUBS R7,R7,#0X01 BNE $PM.LOOP MEND 在程序段中的使用:(使用两次) AA DELAY 0X000005F0 BB DELAY 0X00000FF0 此时调用多次,编译器就不会出现问题,例子中的 AA 和 BB 仅仅是一个标 号,用户可以自行书写,因为在宏指令呗展开时,这个符号在汇编时将使用 相应的值替代。 0x00000FF0 是一个参数 在此处是一个立即数,用户可自行使用为变量等 8、ARM 中的伪操作、伪指令 伪操作—为汇编程序所用,在源程序进行汇编时由汇编程序处理,只在汇编 过程起作用,不参与程序运行。 宏指令—通过伪操作定义的一段独立的代码。在调用它时将宏体插入到源程 序中。 伪指令—是汇编语言程序里的特殊指令助记符,在 汇编时被合适的机器指令 替代。 9、ARM 中 ldr 和 adr 伪指令的区别 一.首先熟悉几个 arm 地址相关的概念: 首先 arm 地址有三个地址概念:编译地址、 期望运行物理地址、实际运行物理地址、 相对地址、绝对地址、位置无关 编译地址 :编译阶段的生成地址,其是相对地址 ,有些地址还没确定,如调用其他.O 文件中的函数或库函数 期望运行物理地址 :链接阶段生成的地址(期望绝对地址 ),会确定编译阶段没有确 定的地址,并会根据链接器假设期望的程序烧录运行物理启始地址 ,来分配期望运行 物理地址 实际运行物理地址 :当程序被烧写到系统(实际绝对地址 ),实际加载运行时,又有 一个实际的程序烧录运行物理启始地址,这个时候进行相应的转换得到实际运行物理地 址 位置无关 :和实际烧写运行的地址无关 二.根据以上的地址概念,来分析 ldr 和 adr/adrl 伪指令的区别 1. ldr ldr r1, =_start 实际上会被编译器改成两条语句: 0x00 ldr r1,[pc, #0x0c] 编译器知道 DCD 的地址,相对于 ldr 的地址偏移量,所以用 ldr 指令从此地址中取出 0x64 .... 0x0c DCD 0x64 /*其中 0x64 就是_start 第一条指令的链接地址(作为标号_start 本身是不占存储空间的), DCD 分配了存储空间用于存放 0x32,此空间成为文字池(literal pool)因为 ldr 命令(非 伪指令)的最后一个操作数为 12 位,所以 ldr 的寻址范围为前后 4KB,即文字池所处 的范围,但文字池中的地址值是 32 位的,所以 ldr 伪指令的实际寻址空间是 32 位的, 其中的 0x64 是期望运行物理地址,当实际代码烧写运行的位置不同时即实际运行物理 地址与期望运行物理地址不同时,则代码运行错误,所以是位置相关的。*/ _start: 0x64 MOVE r0,r0 2. adr adr r1, _start 实际上会被编译器改成一条语句: 0x00 add r1, pc, #0x64 /*被转换成加/减指令、编译器知道 MOVE 指令相对当前指令的偏移量(0x64),从而将 MOVE 的地址赋与 r1 这里取地址的方式是根据当前 PC 的值加上偏移量获取的,不管程序烧写运行在何处, 取得的地址都是合法的,所以是位置无关的。 其最后一个操作数是 12 位的,所以其寻址空间前后只能为 4KB*/ _start: 0x64 MOVE r0,r0 3. Adrl 转化成两个 ADD,寻址空间是 8KB 4.综述 所以综上所述,ldr 和 adr 的区别主要就是地址的位置无关性的差别。ldr 伪指令操作, 一旦实际运行物理地址和期望运行物理地址存在差别,那就会造成程序运行错误。虽然 adr 有这么多优点,但是 adr 的寻址空间只有前后 4kb,而且必须在同一个代码段中, ldr 就没有这些要求。 10、左移运算 SHL、LSL,右移运算 SHR、LSR LSL --MOV R0, R1, LSL#2(ASL#2) ;将 R1 中的内容左移两位后传送 到 R0 中,低位用 0 填充。 LSR-- MOV R0, R1, LSR#2 ;将 R1 中的内容右移两位后传送到 R0 中, 左端用零来填充。 11、源文件 源文件就是用汇编语言或高级语言写出来的代码保存为文件后的结果。 目标文件是指源文件经过编译程序产生的能被 cpu 直接识别二进制文件。 可 执行文件就是将目标文件连接后形成的可执行文件,当然也是二进制的。 12、BootLoader 什么意思 简单地说,BootLoader 就是在操作系统内核运行之前运行的一段小程序。 通过这段小程序,我们可以初始化硬件设备、建立内存空间映射图,从而将 系统的软硬件环境带到一个合适状态,以便为最终调用操作系统内核准备好 正确的环境。在嵌入式系统中,通常并没有像 BIOS 那样的固件程序(注, 有的嵌入式 CPU 也会内嵌一段短小的启动程序),因此整个系统的加载启 动任务就完全由 BootLoader 来完成。比如在一个基于 ARM7TDMI core 的 嵌入式系统中,系统在上电或复位时通常都从地址 0x00000000 处开始执行, 而在这个地址处安排的通常就是系统的 BootLoader 程序。 13、sprintf 函数的用法 格式化数字字符串 sprintf 最常见的应用之一莫过于把整数打印到字符串中,所以,spritnf 在 大多数场合可以替代 itoa。如: sprintf(s, "%d", 123); //产生"123" ,把整数 123 打印成一个字符串保存在 s 中。 控制浮点数打印格式 浮点数的打印和格式控制是 sprintf 的又一大常用功能,浮点数使用格式 符”%f”控制,默认保留小数点后 6 位数字,比如: sprintf(s, "%f", 3.1415926); //产生"3.141593" 14、ARM 处理器的 Remap 什么是 Remap ? 我的理解是:在 ROM 从 0x0 用几句指令引导系统之后,把 RAM 映射到 0x0 就是 Remap。 1、Remap 的作用 当 ARM 处理器上电或者 Reset 之后,处理器从 0x0 取指。因此,必须保 证系统上电时,0x0 处有指令可以执行。所以,上电的时候,0x0 地址处 必定是 ROM 或者 Flash(NOR)。 但是,为了加快启动的速度,也方便可以更改异常向量表,加快中断响应 速度,往往把异常向量表映射到更快、更宽(32bit/16bit)的 RAM 中。但 是异常向量表的开始地址是由 ARM 架构决定的,必须位于 0x0 处,因此, 必须把 ROM 映射到 0x0。 2、Remap 的配置 Remap 的实现和 ARM 处理器的实现相关。 1、如果处理器有专门的寄存器可以完成 Remap。那么 Remap 是通过 Remap 寄存器的相应 bit 置 1 完成的。如 Atmel AT91xx 2、如果处理器没有专门的寄存器,但是 memory 的 bank 控制寄存器可 以用来配置 bank 的起始地址,那么只要把 RAM 的起始地址编程为 0x0, 也可以完成 remap。如 samsung s3c4510 3、如果上面两种机制都没有,那么 Remap 就不要做了。因为处理器实 现决定了 SDRAM 对应的 bank 地址是不能改变的。如 Samsung S3c2410. 3.Remap 配置前后要做的工作 Remap 前后,不同之处就是 RAM 的位置变了。为了达到 Remap 的目的, 就是加快启动的速度和异常处理速度,一定要初始化异常堆栈和建立异常向 量表的。 4.如果象 2410 那样不能 Remap 的话怎么办? 2410 不是不能 Remap 吗?为了加快启动速度,可以这样做 1、使用它的 NAND boot 模式。为什么 NAND boot 会比较快,那是因为 2410 里面有块小石头——“SteppingStone”,一块 4KB SRAM,它是映射在 0x0 的。启动程序会自动被 copy 到这个石头里面。自然异常向量的入口放到这个 地方,一样可以达到比 NOR boot 快的启 动、异常响应速度。 2、如果你对 NOR Boot 情有独衷,那么你只好把你的异常向量的入口 copy 到 SDRAM 里面,实现所谓的 High Vector 15、Semihosing SWI 上面提到许多库函数在调试环境下的实现都调用了一种叫作 semihosting (半主机)的机制。Semihosting 具体来讲是指一种让代码在 ARM 目标上运行, 但使用运行了 ARM 调试器的主机上 I/O 设备;也就是让 ARM 目标将输入/ 输 出请求从应用程序代码传递到运行调试器的主机的一种机制。通常这些输入/输 出设备包括键盘、屏幕和磁盘 I/O。 半主机由一组已定义的 SWI 操作来实现,如图 5 所示。库函数调用相应的 S WI(软件中断),然后调试代理程序处理 SWI 异常,并提供所需的与主机之间的 通讯。多数情况下,半主机 SWI 是由库函数内的代码调用的。但是应用程序也可 以直接调用半主机 SWI。半主机 SWI 的接口函数是通用的。当半主机操作在硬 件仿真器、指令集仿真器、RealMonitor或Angel下执行时,不需要进行移植处理。 图 5 semihosting 的实现过程 使用单个 SWI 编号请求半主机操作。其它的 SWI 编号可供应用程序或操 作系统使用。用于半主机的 SWI 号是: 在 ARM 状态下:0x123456 在 Thumb 状态下:0xAB SWI 编号向调试代理程序指示该 SWI 请求是半主机请求。要辨别具体的操 作类型,用寄存器 r0 作为参数传递。r0 传递的可用半主机操作编号分配如下: ◆ 0x00~0x31:这些编号由 ARM 公司使用,分别对应 32 个具体的执行函 数 ◆ 0x32~0xFF:这些编号由 ARM 公司保留,以备将来用作函数扩展。 ◆ 0x100~0x1FF:这些编号保留给用户应用程序。但是,如果编写自己的 S WI 操作,建议直接使用 SWI 指令和 SWI 编号,而不要使用半主机 SWI 编号 加这些操作类型编号的方法。 ◆ 0x200~0xFFFFFFFF:这些编号未定义。当前未使用并且不推荐使用这 些编号。半主机 SWI 使用的软件中断编号也可以由用户自定义,但若是改变 了缺省的软中断编号,需要: ◆ 更改系统中所有代码(包括库代码)的半主机 SWI 调用 ◆ 重新配置调试器对半主机请求的捕捉与响应这样才能使用新的 SWI 编 号。 16、arm启动函数中 Reset_Addr DCD Reset_Handler 的 DC D 是什么意思? DCD 指令是一个伪指令: 分配连续的字空间,并用指定的数据初始化。这里就是分配一个字的空间, 内 容就是 Reset_Handler 标号处的地址。 这个主要是弥补 b 指令跳转范围太小的问题。 CPU 复位后,首先执行 0 地址处的指令,是一条 b Reset_Addr 的指令。 中段向量表先跳转到 Reset_Addr 处,然后再跳转到 Reset_Handler 标号处, 这样就可以实现 4GB 的全地址跳转。 17、ARM 处理器采用 Load-store 体系结构。故他只有两种类型的指令:load 指令从存储器复制数据到内核的寄存器,store 指令从寄存器里复制数据到存储 器,没有直接操作存储器的数据处理指令。 18、ARM 寄存器分为通用寄存器和状态寄存器两类。状态寄存器保存 ALU 中 的操作信息。通用寄存器包括 R0~R15。R0~R7 是在所有工作模式下通用的寄 存器。R8~R14 每一次所访问的物理寄存器与当前的工作模式有关。其中,寄存 器 R13 在 ARM 指令中常用作堆栈指针。R14 也称作子程序连接寄存器或连接 寄存器 LR。当执行 BL 子程序调用指令时,R14 得到 R15 的备份。其他情况下, R14 用作通用寄存器。R15 用作程序计数器(PC),控制程序指令的执行顺序。 19、Thumb 状态下的寄存器组织与 ARM状态下寄存器组织的关系: Thumb 状态下和 ARM 状态下的 R0~R7 是相同的。 Thumb 状态下和 ARM 状态下的 CPSR、SPSR 相同。 Thumb 状态下的 SP 对应于 ARM 状态下的 R13。 Thumb 状态下的 LR 对应于 ARM 状态下的 R14。 Thumb 状态下的程序计数器对应于 ARM 状态下的 R15。 Thumb 状态 ARM 状态 R0 R0 R1 R1 R2 R2 R3 R3 R4 R4 R5 R5 R6 R6 R7 R7 R8 R9 R10 R11 R12 StackPoint(PC) StackPoint(PC) Link Register(LR) Link Register(LR) ProgramCounter(PC) ProgramCounter(PC) CPSR CPSR SPSR SPSR 20、非对齐的存储器访问 所谓非对齐的存储访问操作是指:位于 ARM 状态期间,访问地址的低二位不为 00;位于 Thumb 状态期间,访问地址的最低位不为 0。

下载文档,方便阅读与编辑

文档的实际排版效果,会与网站的显示效果略有不同!!

需要 5 金币 [ 分享文档获得金币 ] 1 人已下载

下载文档

相关文档