ARM 调试时的DIsassembly窗口的汇编,LDR, MOV,STR

本文深入解析ARM处理器的RISC架构,详细介绍了数据加载与存储指令LDR/STR,寄存器间值传递与立即数赋值指令MOV的使用方法及限制,探讨了MOV指令的直接与间接寻址能力,为理解ARM处理器的底层操作提供了关键信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述
1、ARM是RISC结构,数据从内存到CPU(寄存器)之间的移动LDR/STR指令。
LDR r0, 0x12345678 就是把0x12345678这个地址中的值存放到r0中。
LDR r0,[pc,#48]; 从pc+48存储器取出数据—>存到r0中

2、STR r0,[r1,#0x00] 将r0中的数据写入 r1+0x00 的存储器中

3、MOV r0,#0x1c200 给寄存器r0一个立即数 0x1c200;如果是MOVS指令,则会影响CPSR(当前程序状态寄存器)中的标志位:N位 结果是否为负数,C位:进位移位借位溢出位 V位:overflow位 Z位:结果是否为0

以下说到MOV的立即数不能大于255,但是上面的0x1c200明显大于255,不知为何
参考:https://blog.youkuaiyun.com/czxyhll/article/details/7853807

Question on MOV
Does the instruction “Mov” have indirect addressing?
Answer. No, e.g. you cannot use mov r1,[r2] 
“MOV loads a value into the destination register, from another register, a shifted register, or an immediate 8-bit value.”

Examples:
  MOV R0, R1 if R1 has 0x00001234, after this ,R1=R2=0x00001234
  MOV R0, #0x12; after this R0 has #0x12
  MOV R0, #300; is wrong the value should be less than 255
  MOV R0, 200; is wrong, # is missing “mov R0,#200: is correct

Note: the immediate value must be prefixed by #

从上面的描述可以看出,mov的作用有两个:

  1. 在寄存器之间传递值。

  2. 给寄存器传递一个立即数,此时需要用“#”来修饰立即数,并且立即数为8位的,其值不能超过255.

但是在vivi中的head.S里,有许多类似 mov r1, #0x53000000 的语句:

<think>好的,用户想了解如何在ARM Cortex-M0内核中查看或使用LR寄存器。我需要结合之前的回答和用户提供的引用来给出准确的信息。 首先,用户之前的回答已经详细讲解了PC、SP和LR寄存器的作用。现在用户特别关注LR寄存器。根据引用[1],M0有一些特殊寄存器需要通过MSR/MRS指令访问,但LR是否属于这类呢?可能需要进一步确认。引用[2]提到R0-R12和SP,但LR是R14,属于通用寄存器的一部分吗?根据之前的回答,LR是链接寄存器,用于存储返回地址,所以在函数调用BL指令会自动保存到LR。引用[3]中的示例展示了PC的使用,但LR的使用可能需要类似的方法。引用[5]提到在中断发生,如果函数没有保存LR,可能导致错误,这涉及到中断处理中的LR保存问题。 用户的问题分为两部分:查看LR的值和使用方法。查看的话,可以通过调试器读取,或者在汇编中通过MOV指令将LR的值转移到其他寄存器再查看。使用方法方面,主要是函数调用的自动保存,以及在异常处理中的EXC_RETURN值。此外,需要注意在嵌套调用或中断手动保存LR到堆栈,避免覆盖。 需要确保回答覆盖直接查看方法、编程中的使用示例,以及注意事项,比如中断中的LR处理。同,引用相关的参考文献,比如引用[5]提到的中断中LR保存的问题,可以作为注意事项的一部分。还要提醒用户LR在异常处理中的特殊值,如EXC_RETURN,这可能影响返回模式。 最后,生成相关问题要围绕LR的使用场景、调试方法、异常处理等,帮助用户深入理解。</think>### ARM Cortex-M0 LR寄存器查看与使用指南 #### 一、直接查看LR寄存器值的方法 1. **调试器实读取** 通过JTAG/SWD调试接口(如ST-Link、J-Link)连接芯片,在调试暂停状态下可直接查看$LR$寄存器值。例如在Keil MDK中: - 打开`Register`窗口 - 查找`LR (R14)`条目 - 实显示十六进制格式的数值,如`0x08000123` 2. **汇编代码读取(需手动操作)** 通过$MOV$指令将$LR$值转移到通用寄存器后输出: ```asm MOV R0, LR ; 将LR值复制到R0 BL PrintHex ; 调用打印函数显示R0值 ``` > 注:需要自定义打印函数支持[^3] #### 二、LR寄存器核心使用场景 1. **函数调用与返回** 通过$BL$指令自动保存返回地址: ```asm main: BL sub_func ; 执行后LR = main+4 B exit sub_func: PUSH {LR} ; 必须手动保存嵌套调用的LR ... POP {PC} ; 等效于BX LR ``` 2. **异常/中断处理** 进入异常硬件自动将$LR$设置为特殊值$EXC\_RETURN$,用于指示返回模式: $$ EXC\_RETURN = \begin{cases} 0xFFFFFFF1 & 返回Handler模式使用MSP \\ 0xFFFFFFF9 & 返回Thread模式使用MSP \\ 0xFFFFFFFD & 返回Thread模式使用PSP \end{cases} $$ 3. **手动操作场景** 通过汇编指令直接修改: ```asm LDR LR, =0x0800FF00 ; 强制设置返回地址 BX LR ; 跳转到指定地址 ``` #### 三、关键注意事项 1. **中断服务程序保护** 若中断可能打断无栈帧的函数(如`add()`等叶子函数),必须手动保存$LR$: ```asm ISR_Handler: PUSH {R0-R3, LR} ; 强制保存LR[^5] ... POP {R0-R3, PC} ; 通过PC恢复实现返回 ``` 2. **嵌套调用保护** 当函数内部再次调用子程序,必须通过压栈保护$LR$原始值: ```asm func_level1: PUSH {LR} ; 保存上级返回地址 BL func_level2 POP {PC} ; 恢复返回地址 func_level2: ... ; 无需再保存(无嵌套调用) ``` 3. **调试异常定位** 当发生HardFault,通过检查$LR$值可确定异常发生前状态: - $LR=0xFFFFFFF9$:异常发生在使用MSP的线程模式 - $LR=0xFFFFFFFD$:异常发生在使用PSP的线程模式 #### 四、实践验证方法 1. **Keil调试模式验证** - 在`Disassembly`窗口单步执行函数调用 - 观察`LR`寄存器的自动更新过程 2. **内存窗口观察** ```asm MOV R0, LR STR R0, [SP, #-4]! ; 将LR值存储到栈顶 ``` 通过Memory窗口查看堆栈区域数据 3. **断点触发验证** 在异常处理入口设置断点,捕获$EXC\_RETURN$值 #### 五、典型错误案例 ```asm ; 错误示例:未保存LR导致返回地址丢失 unsafe_func: BL sub_func ; LR被覆盖为sub_func返回地址 BX LR ; 此处实际返回到调用sub_func的位置,而非上级调用者 ``` --相关问题-- 1. Cortex-M0异常返回如何根据EXC_RETURN切换堆栈指针? 2. 如何通过LR寄存器值分析HardFault发生位置? 3. 在混合C/汇编编程中如何确保LR寄存器正确传递? [^1]: Cortex-M4/7特殊寄存器访问方式参考 [^3]: PC寄存器操作示例 [^5]: 中断服务中的LR保护必要性
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值