汇编.s文件

https://zhuanlan.zhihu.com/p/98888285

汇编指令

BX

  • BX指令:在ARM汇编语言中,BX指令用于跳转到指令中所指定的目标地址。这个目标地址可以是ARM指令,也可以是Thumb指令。BX指令的格式为:BX {条件} 目标地址。这个指令的特点是它可以改变处理器的状态,从ARM状态切换到Thumb状态,或者从Thumb状态切换到ARM状态。这种状态切换的功能使得BX指令在实现子程序调用和处理器工作状态切换时非常有用。

LR链接寄存器

  • LR链接寄存器:在ARM架构中,链接寄存器(Link Register,简称LR)通常用于存储子程序返回地址。当执行BL(带返回的跳转指令)或BLX(带返回和状态切换的跳转指令)时,处理器会将下一条指令的地址保存到LR中。然后,当子程序执行完毕后,可以通过将LR的内容加载到程序计数器(PC)中,从而返回到调用者。这种机制使得子程序的调用和返回变得非常方便和高效。

  • 在用户模式下,LR(或R14)用作链接寄存器,用于存储子程序调用时的返回地址。如果返回地址存储在堆栈上,它也可以用作通用寄存器。

    在异常处理模式中,LR 保存异常的返回地址,或者如果在异常内执行子例程调用,则保存子例程返回地址。如果返回地址存储在堆栈中,LR 可以用作通用寄存器。

[]的作用

  • 在这段ARM汇编代码中,LDR r3, [r2] 是一条加载指令。这条指令的作用是从内存中加载数据。

  • r3 和 r2 是寄存器,它们是CPU中用于临时存储数据的小存储区。在这个上下文中,r3 和 r2 只是寄存器的名称,它们没有特殊的含义,只是用于标识这些寄存器。

    [r2] 的含义是:使用 r2 寄存器中的值作为内存地址,从该地址加载数据。[] 的作用是表示间接寻址,也就是说,我们不是直接使用 r2 的值,而是使用 r2 中的值作为一个内存地址,从这个地址中获取数据。

    所以,LDR r3, [r2] 的整体含义是:从内存中的 r2 所指向的地址加载数据,然后将这些数据存储到 r3 寄存器中。这就是这条指令的作用。

简单的指令

  • LDR: 将地址加载到寄存器中。
  • CMP: 比较两个操作数的值。
  • BEQ

MSR

  • MSR指令[1][2][3][4]:在ARM汇编语言中,MSR(Move to Status Register)指令用于将操作数的内容传送到程序状态寄存器的特定域中。其中,操作数可以为通用寄存器或立即数。MSR指令通常用于恢复或改变程序状态寄存器的内容。例如,当需要修改状态寄存器的内容时,可以通过“读取-修改-写回”指令序列完成。这种操作通常用于切换处理器模式、或者允许/禁止IRQ/FIQ中断等。

PRIMASK寄存器

  • PRIMASK寄存器[5][6][7]:在ARM Cortex-M处理器中,PRIMASK寄存器用于控制中断的优先级,允许屏蔽(禁止)特定优先级的中断。PRIMASK寄存器是一个单比特(bit)的寄存器,只有两个有效的取值:0和1。当PRIMASK寄存器的值为0时,表示所有中断都可以触发。当PRIMASK寄存器的值为1时,会禁止所有可屏蔽的中断。这意味着通过设置 PRIMASK 寄存器为 1,可以禁用所有中断,从而实现临界区的保护或者实现禁止中断的功能。

中断启用禁用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

/*

* rt_base_t rt_hw_interrupt_disable();

*/

.global rt_hw_interrupt_disable

.type rt_hw_interrupt_disable, %function

rt_hw_interrupt_disable:

//将PRIMASK写入RO寄存器

MRS r0, PRIMASK

//设置CPSID为I,用于禁用中断

CPSID I

BX LR


/*

* void rt_hw_interrupt_enable(rt_base_t level);

*/

.global rt_hw_interrupt_enable

.type rt_hw_interrupt_enable, %function

rt_hw_interrupt_enable:

//从RO取回PRIMASK

MSR PRIMASK, r0

BX LR

  • 由于将PRIMASK的值暂存在r0中,执行临界段代码时r0值会不会改变?

https://club.rt-thread.org/ask/question/d5156cdf3abb63a1.html

HardFault_Handler

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

.global HardFault_Handler

.type HardFault_Handler, %function

HardFault_Handler:

/* 获取当前上下文 */

MRS r0, msp /* 从处理程序获取故障上下文 */

TST lr, #0x04 /* 如果!EXC_RETURN[2] */

BEQ _get_sp_done

MRS r0, psp /* 从线程获取故障上下文 */

_get_sp_done:


STMFD r0!, {r4 - r11} /* 压入r4 - r11寄存器 */

#if defined (__VFP_FP__) && !defined(__SOFTFP__)

STMFD r0!, {lr} /* 压入标志的占位符 */

#endif

STMFD r0!, {lr} /* 压入exec_return寄存器 */


TST lr, #0x04 /* 如果!EXC_RETURN[2] */

BEQ _update_msp

MSR psp, r0 /* 更新堆栈指针到PSP */

B _update_done

_update_msp:

MSR msp, r0 /* 更新堆栈指针到MSP */

_update_done:


PUSH {LR}

BL rt_hw_hard_fault_exception /* 调用硬件故障异常处理函数 */

POP {LR}


ORR lr, lr, #0x04

BX lr /* 返回 */