一、ARM汇编指令
- 
mov: 将一个值或寄存器的内容移动到另一个寄存器中。这个指令可以用来赋值。 示例: mov r0, #5// 将立即数 5 移动到寄存器 r0
- 
add: 执行加法操作,将两个操作数相加,并将结果存储在目标寄存器中。 示例: add r0, r1, r2// 将 r1 和 r2 的值相加,并将结果存储在 r0 中
- 
sub: 执行减法操作,从一个寄存器的值中减去另一个寄存器的值,并将结果存储在目标寄存器中。 示例: sub r0, r1, r2// 计算 r1 - r2 的值,并将结果存储在 r0 中
- 
ldr: 从内存中加载数据到寄存器中。 示例: ldr r0, [r1]// 从 r1 指向的地址加载数据到 r0 中
- 
bic: 对两个操作数执行按位清除运算,保留第一个操作数中的位,而将第二个操作数中的位清零。 示例: bic r0, r1, r2// 清除 r1 中与 r2 中相同的位,将结果存储在 r0 中
- 
orr: 对两个操作数执行按位或运算。 示例: orr r0, r1, r2// 将 r1 和 r2 的位进行按位或运算,结果存储在 r0 中
- 
cmp: 比较两个寄存器中的值,设置相应的标志位(如零标志、负标志等),但不存储结果。 示例: cmp r0, r1// 比较 r0 和 r1 的值
- 
stmfd: 将多个寄存器的内容存入内存,按全降序存储,通常用于保存寄存器状态。 示例: stmfd sp!, {r0, r1, r2}// 将 r0, r1, r2 存储到栈中
- 
ldmfd: 从内存中加载多个寄存器的内容,按全升序恢复寄存器状态。 示例: ldmfd sp!, {r0, r1, r2}// 从栈中加载 r0, r1, r2 的值
二、跳转语句
- 
b: 无条件跳转指令,跳转到指定的标签或地址。这是ARM汇编中最常用的跳转指令。 示例: b label// 跳转到名为 label 的位置
- 
bl: 带链接的跳转,除了跳转到指定地址外,还将返回地址(下一条指令的地址)保存到链接寄存器(LR 或 r14)中。常用于子程序调用。 示例: bl function// 跳转到 function,并将返回地址存储在 LR 中
- 
bx: 通过指定的寄存器地址跳转,并且可以根据寄存器的最低位设置处理器的状态(如进入 ARM 或 Thumb 状态)。它通常用于从子程序返回。 示例: bx r0// 跳转到 r0 寄存器中存储的地址
栈指针寄存器
- SP(栈指针寄存器) : SP 寄存器用于指向当前栈的顶部。栈通常用于存储局部变量、保存返回地址等。当使用 stmfd和ldmfd指令时,stack pointer (SP) 寄存器可用于管理函数调用和返回。
CPSR 寄存器相关指令
- 
mrs: 从 CPSR(当前程序状态寄存器)读取数据。当需要获取当前状态或标志位时,使用此指令。 示例: mrs r0, cpsr// 将 CPSR 的值加载到 r0 中
- 
msr: 设置 CPSR 的某些位。这可以用于改变处理器的状态或控制特权级别。 示例: msr cpsr_c, r0// 将 r0 的内容写入 CPSR 中的控制位
三、汇编
preserve8               ; 保留8字节对齐  
area reset, code, readonly ; 定义一个名为"reset"的只读代码区域  
code32                  ; 设定代码为32位  
entry                   ; 定义入口点  
b start                 ; 跳转到 start 标签,开始程序执行  
ldr pc, =do_undifined   ; 将 do_undifined 的地址加载到程序计数器(PC),设置未定义指令处理  
ldr pc, =do_swi        ; 将 do_swi 的地址加载到 PC,设置软件中断处理  
ldr pc, =do_p_abort    ; 将 do_p_abort 的地址加载到 PC,设置预取中止处理  
ldr pc, =do_d_abort    ; 将 do_d_abort 的地址加载到 PC,设置数据中止处理  
nop                     ; 空操作,通常用于填充或延迟  
ldr pc, =do_irq        ; 将 do_irq 的地址加载到 PC,设置外部中断处理  
ldr pc, =do_fiq        ; 将 do_fiq 的地址加载到 PC,设置快速中断处理  
do_fiq                  ; 快速中断处理程序  
	b do_fiq              ; 无限循环,等待快速中断  
do_irq                  ; 外部中断处理程序  
	import irq_handler    ; 导入 irq_handler 函数  
	sub lr, lr, #4        ; 将链接寄存器(LR)减去4,以调整返回地址  
	stmfd sp!, {r0-r12, lr} ; 将 r0-r12 和 LR 保存到栈中,进行现场保护  
	bl irq_handler        ; 调用中断处理程序  
	ldmfd sp!, {r0-r12, pc}^ ; 恢复寄存器并返回  
do_d_abort              ; 数据中止处理程序  
	b do_d_abort          ; 无限循环,等待数据中止  
do_p_abort              ; 预取中止处理程序  
	b do_p_abort          ; 无限循环,等待预取中止  
do_swi                  ; 软件中断处理程序  
	import swi_handler     ; 导入 swi_handler 函数  
	stmfd sp!, {r0-r12, lr} ; 保存 r0-r12 和 LR 到栈中  
	bl swi_handler        ;  调用软件中断处理程序  
	ldmfd sp!, {r0-r12, pc}^ ; 恢复寄存器的工作模式并返回
do_undifined            ; 未定义指令处理程序  
	b do_undifined        ; 无限循环,等待未定义指令  
start                   ; 程序启动点  
	ldr sp, =0x40001000  ; 将栈指针(SP)初始化为指定地址  
	mrs r0, cpsr          ; 读取当前程序状态寄存器(CPSR)  
	bic r0, r0, #0x1F     ; 清除 CPSR 中的模式位  
	orr r0, r0, #0x12    ; 设置 CPSR 进入 irq 模式  
	bic r0, #(1 << 7)     ; 清除 CPSR 中的 F 标志位  
	msr cpsr_c, r0       ; 更新 CPSR  
	ldr r0, =0x40001000  ; 将地址 0x40001000 加载到 r0   
	sub r0, r0, #1024    ; 计算栈顶地址  
	mov sp, r0           ; 设置栈指针 SP  
	mrs r0, cpsr          ; 读取当前 CPSR  
	bic r0, r0, #0x1F     ; 清除模式位  
	orr r0, r0, #0x10    ; 设置 CPSR 进入 user 模式  
	msr cpsr_c, r0       ; 更新 CPSR  
	ldr r0, =0x40001000  ; 将地址 0x40001000 加载到 r0  
	sub r0, r0, #2048    ; 计算新的栈顶地址  
	mov sp, r0           ; 设置栈指针 SP  
	import main           ; 导入 main 函数  
	b main               ; 跳转到 main 函数  
asm_fn                  ; 汇编函数的标签  
	export asm_fn         ; 导出 asm_fn 函数  
	swi #7                ; 触发软件中断,调用系统服务  
	bx lr                 ; 返回到调用者  
finished                ; 完成标签  
	b finished            ; 无限循环,等待程序结束  
	end                    ; 汇编代码的结束标志