大一网站开发项目答辩WordPress主题文本
news/
2025/9/27 23:11:09/
文章来源:
大一网站开发项目答辩,WordPress主题文本,公司域名备案,中信建设证券有限责任公司1. 前言 如图1所示#xff0c;R14是连接寄存器#xff08;Link Register#xff09;#xff0c;在汇编指令中通常也写为LR#xff0c;用于存储函数调用和异常等的返回信息#xff0c;复位时#xff0c;默认值为0xFFFFFFFF#xff1b; 图1 Core register R15是程序计数…1. 前言 如图1所示R14是连接寄存器Link Register在汇编指令中通常也写为LR用于存储函数调用和异常等的返回信息复位时默认值为0xFFFFFFFF 图1 Core register R15是程序计数器PCProgram Counter)复位后初始值为Vector Table(中断向量表的首地址加上0x04Reset向量其bit[0的值为必须1并会加载到EPSR(Execution Program Status Register)的T字段Thumb state bit表示处于Thumb状态。ARM-v7只支持在Thumb下执行指令在T字段为0的情况下执行任何指令都将导致错误或锁定。 如下所示向量表的首地址存放的是MSP的初始地址偏移四字节后即是Reset_Handler也就是说代码复位后是从Reset_Handler开始运行的。 const pFunc __VECTOR_TABLE[256] __VECTOR_TABLE_ATTRIBUTE {(pFunc)(__INITIAL_SP), /* Initial Stack Pointer */Reset_Handler, /* Reset Handler */NMI_Handler, /* -14 NMI Handler */HardFault_Handler, /* -13 Hard Fault Handler */MemManage_Handler, /* -12 MPU Fault Handler */BusFault_Handler, /* -11 Bus Fault Handler */UsageFault_Handler, /* -10 Usage Fault Handler */0, /* Reserved */0, /* Reserved */0, /* Reserved */0, /* Reserved */SVC_Handler, /* -5 SVCall Handler */DebugMon_Handler, /* -4 Debug Monitor Handler */0, /* Reserved */PendSV_Handler, /* -2 PendSV Handler */SysTick_Handler, /* -1 SysTick Handler *//* Interrupts */Interrupt0_Handler, /* 0 Interrupt 0 */Interrupt1_Handler, /* 1 Interrupt 1 */Interrupt2_Handler, /* 2 Interrupt 2 */Interrupt3_Handler, /* 3 Interrupt 3 */Interrupt4_Handler, /* 4 Interrupt 4 */Interrupt5_Handler, /* 5 Interrupt 5 */Interrupt6_Handler, /* 6 Interrupt 6 */Interrupt7_Handler, /* 7 Interrupt 7 */Interrupt8_Handler, /* 8 Interrupt 8 */Interrupt9_Handler /* 9 Interrupt 9 *//* Interrupts 10 .. 255 are left out */
}; 对于PC来说其相关的表达式或标签label)指示着一条指令或数据的地址目标位置如果PC当前位置到目标位置的偏移量大的过分编译器会报错。由于ARM-v7采用了指令流水线技术所以读PC的返回值是当前指令地址4且返回值的LSB为0(Thumb指令至少半字对齐)例如
0x1000: MOV R0, PC ; R0 0x1004 具体来说 ①对于B、BL、CBNZ和CBZ指令PC的值是当前指令地址加上4字节 ②对于其他使用label的指令来说PC的值是当前指令地址加上4字节且指令执行后PC的值的bit[1]会被强制清零以保证其值按字长word)对齐。 此外向PC中写数据就会引起一次程序分支不更新LR寄存器但无论是直接写PC还是使用分支转移指令都必须保证加载到PC的值的LSB为1即bit[0]为1用以表明是在Thumb状态下执行
2.相关汇编指令
2.1 PUSH/POP PUSH和POP指令适用于寄存器的压栈和出栈且必须是满减栈full descending stack:
表1 PUSH/POP指令 PUSH condition {reglist}reglist中不可包含PC(独一无二的PC不允许有影子的存在说一不二)POP condition {reglist}reglist中不可同时包含PC和LR(既生瑜何生亮) 其中: ①conditon为条件码可选 ②reglist为非空寄存器列表列表元素可以是寄存器或寄存器子列表range如R0-R2表示R0,R1,R2)如果包含多个寄存器或寄存器子列表则以逗号分隔 ③reglist不可包含SP(医者不能自医啊); ④当 reglist中存在PC时则在POP指令完成时就会跳转到PC所对应的地址执行(该地址必须半字对齐)同时PC对应出栈值的bit[0]会用来更新APSR的T字段T-bit)且该bit的值必须为1以指示Thumb状态此外如果该POP指令带有条件码则必须是IT指令块的最后一条指令。 通常来说PUSH和POP会成对使用且 在PUSH和POP的过程中SP的值会按堆栈的使用规则自动调整。例如如满减栈情况下PUSH的同时SP自减POP的同时SP递增 注意在寄存器列表中不管寄存器序列如何汇编器都将把它们升序排序优先 PUSH序号大的寄存器优先 POP序号小的寄存器例如
PUSH {R0,R4-R7} ; Push R0,R4,R5,R6,R7 onto the stack
PUSH {R2,LR} ; Push R2 and the link-register onto the stack
POP {R0,R6,PC} ; Pop r0,r6 and PC from the stack, then branch to the new PC. 这样就意味着R0最后入栈最先出栈这应该也利于R0的频繁使用吧。 值得一提的是STMDB和LDMIA在以R13SP)为目的寄存器时可以达到与PUSH/POP相同的效果
STMDB SP!, {R0-R3, LR} ;等效于 PUSH {R0-R3, LR}
LDMIA SP!, {R0-R3, PC} ;等效于 PUSH {R0-R3, PC} 2.2 分支branch指令
表2 分支指令branch instrctions 指令跳转范围说明B label-16MB ~ 16MB立即跳转通过立即数或表达式Bcond lable (IT指令块外)-1MB ~ 1MB立即跳转Bcond lable (IT指令块内)-16MB ~ 16MB立即跳转BL{cond} label-16MB ~ 16MB立即跳转同时将返回地址存储到LRBX{cond} RmRm中的任意值通过寄存器间接跳转BLX{cond} RmRm中的任意值通过寄存器间接跳转同时将返回地址存储到LR 其中 ①由于PC的值为当前指令地址4着也就意味着向前跳转的范围多了4个字节 ②label是一个PC相关的表达式表示要跳转到的地址 ③ BX 和 BLX中Rm寄存器的值为跳转的目的地址bit[0]指示跳转后CPU要进入的状态且如前文所述该值的bit[0]必须为1生成地址时会忽略该bit置0如果BL和BLX指令中Rm的bit[0]不为1则会产生一个用法错误异常(UsageFault exception) ④BL和BLX指令会将当前下一条指令的地址存储到LR中以提供返回信息 ⑤Bcond lable是唯一在IT指令块内外都可以使用的条件分支指令对于其余的分支指令在IT指令块内部必须是带条件的IT指令块内部的指令都是条件指令在IT指令块外则必须是无条件的 ⑥在IT指令块内部使用分支指令时则该分支指令必须时IT指令块的最后一条指令 ⑦BLX指令中不可使用PC ⑧使用 .W后缀可以拓展分支跳转范围
3.通过PC控制程序执行
3.1通过 MOV指令
MOV PC, Rn ; branch to the address indicated in Rn 当使用MOV指令将Rn中存储的值赋给PC时该值的bit[0]将会被忽略并跳转到Rn给出的地址中。此外使用MOV指令对PC进行赋值时MOV后不可使用S条件后缀且Rn必须是一个没有移位的寄存器。虽然MOV指令可实现分支跳转但BX或BLX指令更专业移植性也更好。
3.2 通过分支指令
B loopA ; Branch to loopA
BLE ng ; Conditionally branch to label ng
B.W target ; Branch to target within 16MB range
BEQ target ; Conditionally branch to target
BEQ.W target; Conditionally branch to target within 1MB
BL funC ; Branch with link (Call) to function funC, return address stored in LR
BX LR ; Return from function call
BXNE R0 ; Conditionally branch to address stored in R0
BLX R0 ; Branch with link and exchange (Call) to a address stored in R0.
3.3 通过LDR指令
LDR PC, [Rn] ;转移地址存储在 Rn 所指向的存储器中
3.4 通过POP指令 既然LR在子程序调用过程中的唯一用处就是存储返回地址那就直接绕过LR将返回地址传给PC返回子程序调用处例如
push {r0-r3, lr} ;子程序入口
pop {r0-r3, pc} ;子程序出口
4. PC跳转的应用 4.1 程序加载后跳转到resetHandler /**************************************************************************************************Local Functions**************************************************************************************************/uint32 resetHandlerAddr;void Device_Deinit(void);status_t bootUpCurrentCore(uint32_t entryPoint){/* entryPoint为中断向量表(vectortable)的首地址, vectortable[1]的地址为resetHandlerAddr */resetHandlerAddr *((uint32_t*)entryPoint1); Device_Deinit();S32_SysTick-CSRr S32_SysTick_CSR_ENABLE(0u);__asm(ldr r0, resetHandlerAddr); __asm(ldr r1, [r0]); /* r1 *resetHandlerAddr 即r1 resetHandler */__asm(mov pc, r1); /* pc resetHandler, 即跳转到resetHandler函数 */return STATUS_SUCCESS;}
4.2 Reset_Handler函数完成系统初始化
/*----------------------------------------------------------------------------Reset Handler called on controller reset
*----------------------------------------------------------------------------*/
void __attribute__((naked,__noreturn__)) Reset_Handler(void)
{__EARLY_INIT();/* Stack pointer initialisation */__set_CONTROL(0); /* MSP with privilege mode*/__set_PSP(0);__set_BASEPRI(0);__set_MSP((uint32_t)__INITIAL_SP);SystemInit(); /* CMSIS System Initialization */__PROGRAM_START(); /* Enter PreMain (C library entry point) */
}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/920073.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!