ARM基础概念 异常处理01 day52

发布于:2025-08-14 ⋅ 阅读:(17) ⋅ 点赞:(0)

四:ARM汇编语言程序格式

ARM汇编语言是以段(section)为单位来组织源文件的。段是相对独立的、具有特定名称的、不可分割的指令或者数据序列。

段又可以分为代码段和数据段,代码段存放执行代码,数据段存放代码运行时的数据,A搜素解释快速润色总一个ARM源程序至少需要一个代码段,大的程序可以包含多个代码段和数据段。

在汇编文件中,我们需要先定义一个段,在段中添加我们实现的汇编程序语句

一:六大指令集

1.分别为数据处理指令 //(完成CPU内部的计算)

2.Load/Store指令 //(完成CPU与内存IO外设之间的数据传输)

3.跳转指令 //(完成程序的跳转)

4.程序状态寄存器处理指令 //(完成 CPSR的管理)

5.协处理器指令 //(完成CPU扩展功能的实现)

6.异常产生指令 //(用户程序异常触发)

二:指令格式中符号说明

〈opcode〉{〈cond〉}{S}  〈Rd〉,〈Rn〉{,〈operand2〉} 
opcode 			//操作码;指令助记符,如LDR、STR等。         
cond       		//可选的条件码;执行条件,如EQ(相同)、NE(uneq 不相等)等。
S       		//可选后缀;若指定“S”,
       			//则根据指令执行结果更新CPSR中的条件码。
Rd				//目标寄存器。
Rn       		//存放第1操作数的寄存器。
Operand2      	//第2个操作数

三:数据处理指令

算术指令:		  ADD ADC SUB SBC RSB(反向减,就是2 - 1 => 1 - 2) RSC
位 运 算 指令:	 AND(&) ORR(|) EOR(异或) BIC(位清零)
比较指令:		  CMP 	CMN	 	TST 	TEQ
数据搬移:		  MOV 	MVN(按位取反放进去)
    
语法:
    	<操作> 	{<cond>} 	{S} 	Rd, 	Rn, 		Operand2
有比较指令影响标志位 -不指定Rd
数据搬移(MOV指令)不指定Rn
	area reset, code, readonly
	code32
	entry
	
	mov r0,#1  		;1搬移到r0中	  #   不超过256
	mov r1,#2  		;2搬移到r1中
	add r2, r1, r0
	sub r3, r1, r0
	rsb	r4, r0, r1
	and r5, r0, #0xff
	orr r6, r1, #0x01
	eor r7, r0, #0xfe
	bic r8, r7, #0xfe
	mvn r9,#0x01
	adc r10, r1, r0, LSL#1
	;sbc r11, r1, r1, LSL#1
	;rsc r12, r1, r0, LSL#1
	end
3.1进位的问题
;进位adc的使用
	area reset, code, readonly
	code32
	entry
	
	;0x1 ffff ffff
	;0x2 ffff ffff

	mov r0, #0x01 
	mov r1, #0xffffffff 
			
	mov r2, #0x02 
	mov r3, #0xffffffff 	
	
	adds r5, r1, r3		;产生进位
	;产生进位需要+s
	adc r4, r0, r2		;使用进位
	
	end
3.4比较的问题

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

;比较的使用有进位问题,也不需要+s
	cmp r0, r1	;只能两两比较
	movgt r2,r0	 ;大于
	moveq 		;等于
	movgt		;小于
	;所有指令都将可以 + eq 等。。。可选的条件码
	;执行为真才能执行  本质上先运算(真?/假?),在放入
	;图很重要,是判断标志位的启示,可以视为if判断的真假之说
;if判断
mov r0 #4
mov rl #5
mov r2 #3
cmp r0 rl	;先判断r0,r1
cmpgt r0 r2		;上句成立,接着比较  
;为什么用gt,因为涉及到截断特性,不加gt,就随便放入,随便执行了
movgt r3 r0
;1 ~ 100 相加
	area reset, code, readonly
	code32
	entry
	
	mov r0, #1
	mov r1, #0
loop
	add r1, r1, r0
	add r0, r0 ,#1

	cmp r0, #101

	bne loop		;这里用blt还是其他都合理,还是要看标志位
	
	end
3.5立即数

一个数(或按位取反)循环右移2^n(移动偶次)位后中所有的1能放进低8位中 范围0~255

;放非立即数或超过范围
ldr sp, =0x40001000    ;将一个地址加载到寄存器中
mov r0, #1		;将立即数1搬移到r0中, #代表立即数
3.6入栈操作指令
ldr sp, =0x40001000   ;栈顶
;Load/Store指令    入栈只是其中之一
;(完成CPU与内存 IO外设之间的数据传输)
STMFD (Push)	块存储- Full Descending stack [STMDB]
LDMFD (Pop)		块装载-Full Descending stack [LDMIA]
------------------------------------------------
;用法
STMFD sp!,{r4-r7,lr}	;表示为r4 ~ r7  再加上一个lr
LDMFD sp!,{r4-r7,pc}	;入栈出栈的顺序要对  先进后出
3.7函数应用(栈)
ldr sp, =0x40001000   ;栈顶
;例子 
fun
	stmfd sp!,{lr}:;保护现场
	;代码。。。。。。。
	
	ldmfd sp!,{lr}	;恢复现场
3.8声明外部函数.c
preserve8	;当c和汇编语言需要对齐8字节,放在最上面,是关键字

;函数调用规则
;前四个参数,使用r0,r1,r2,r3存放参数,剩余参数使用栈传递
;返回值存放在r0中;
ldr sp, =0x40001000   ;栈顶
mov r0, #1 
mov r1, #1
mov r2, #1
mov r3, #1
mov r4, #1
mov r5, #1
stmfd sp!, {r4,r5}	;用站

import c_add	;声明一个外部符号,给汇编文件使用
bl c_add		;汇编语言不能带参数,不像c

int asm_add(int x,int y);	//c中调汇编,声明

int c_add(int a,int b)
{
	int sum = asm_add(a,b);
	return sum;
}
export asm_add   ;声明一个内部符号给外部文件使用
ldr sp, =0x40001000   ;栈顶

ams_add
	stmfd sp!,{r4 - r12,lr}		;保险,防止数据篡改
	add r0,r0,r1
	ldmfd sp!,{r4 - r12,pc}
3.9出栈代码简化问题
ldmfd sp!, {pc} 
{lr} → 出栈到 LR,相当于“把栈顶值存到返回地址寄存器”,并不直接跳转。

{pc} → 出栈到 PC,相当于“出栈并跳转到该地址”,这常用于函数返回。
3.10更改工作状态
mrs r0 cpsr
bic r0 r0 #0xlf
orr r0 r0 #0x10
msr cpsr_c r0
3.11软中断
swi #5		;软中断指令    进入svc模式
;pc会默认跳到8 
3.12总测试
int asm_add(int x,int y);//c中调汇编,声明

int c_add(int a,int b)
{
	int sum = asm_add(a,b);
	return sum;
}
	preserve8
	area reset, code, readonly
	code32
	entry

	ldr sp, =0x40001000   ;初始化svc模式的栈
    ;进入C程序,里面也涉及到栈的使用

	mrs r0, cpsr
	bic r0, r0, #0x1f
	orr r0, r0, #0x10
	msr cpsr_c, r0
	ldr sp, =0x4000c000		;初始化user模式的栈

	import c_add
	bl c_add
	
	export asm_add   ;声明一个内部符号给外部文件使用



asm_add
	stmfd sp!,{r4-r12,lr}		;保险,防止数据篡改
	mov r0, #1
	mov r1, #1
	add r0,r0,r1
	ldmfd sp!,{r4-r12,pc}

	
	end

五:异常处理

ARM 有两级外部中断 FIQ,IRQ.

可是大多数的基于ARM 的系统有有>2个的中断源,因此需要一个中断控制器

ps:通常中断处理程序总是应该包含清除中断源的代码

为什么:
	外设或事件(比如定时器溢出、GPIO 变化、串口接收)会设置一个中断挂起标志位(pending flag)。
	CPU 检测到这个标志后,进入中断服务程序(ISR)。如果这个标志位不被清除,那么:ISR 执行结束时,CPU 发现中断源还在挂起 → 马上再次进入 ISR。程序就可能死在中断里,永远不回到主程序。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

其中保存返回地址到LR ,软中断pc会默认跳到8

看图的右边偏移量对应就是每种异常pc默认回到的地址

一:异常规范函数

	preserve8
	area reset, code, readonly
	code32
	entry
;这里就是异常向量表   预设
	b start   	; reset
	nop       	; undef
	b deal_swi	; swi
	nop			; prefetch abort
	nop			; data abort
	nop			; reserved
	nop			; irq
	nop			; fiq

deal_swi	;预设
	stmfd sp!, {r4-r12, lr}	  
	add r0, r0, r1
	ldmfd sp!, {r4-r12, pc}   

start

	ldr sp, =0x40001000	  
	
	mrs r0, cpsr
	bic r0, r0, #0x1f
	orr r0, r0, #0x10
	msr cpsr_c, r0	   
	ldr sp, =0x40000C00	   

	swi #5	 ;ÈíÖжÏÖ¸Áî
	mov r0, #1
	mov r1, #2
	import c_add	
	bl c_add	 

	nop     
	b start
	
	export asm_add	   
asm_add
	stmfd sp!, {r4-r12, lr}	  
	add r0, r0, r1
	ldmfd sp!, {r4-r12, pc}  

	end	






网站公告

今日签到

点亮在社区的每一天
去签到