ARM_s5pv210_arm_8

来源:互联网 发布:2144传奇盛世翅膀数据 编辑:程序博客网 时间:2024/06/08 12:32

回顾:
指令集:
跳转指令:B BL BX
数据处理指令:
1.数据传送
2.算术运算
3.位运算
4.比较测试
操作码{条件}S 目标寄存器,第一源操作数,第二源操作数

加载存储指令:
单寄存器:
LDR Rd,<地址模式>
LDRB Rd,<地址模式>
基址 + 偏移量(立即数,寄存器,寄存器移位)
LDRH Rd,<地址模式>
LDRSH Rd,<地址模式>
LDRSB Rd,<地址模式>
基址 + 偏移量(立即数,寄存器)
STR Rd,<地址模式>
STRH Rd,<地址模式>
STRB Rd,<地址模式>

多寄存器:
LDM Rb!,{R0,R1,R2}
STM
IA
IB
DA
DB都是指的如何操作地址的


满减栈
Push STMDB STMFD
Pop LDMIA LDMFD

MRS 读CPSR,SPSR
MSR 写CPSR,SPSR

伪指令:
ADR
ADRL
LDR
示例:
(1) LDR PC,label
label:
.word 0x12345678
(2)LDR R0,=label
LDR PC,[R0]
label:
.word 0x12345678
NOP

/*********************************************/
伪操作
main:mov r1,r0 @主程序入口
test.s示例
.text @指定代码放到.text段
.global do_sub @声明全局标号
do_sub:
sub r0,r0,r1 @两个数相减
mov pc,lr @子程序返回
.end

伪操作:汇编语言程序里的一些特殊助记符为编程方便,完成一些辅助功能的操作。
在对汇编源程序进行汇编过程中有汇编程序处理,而不是在程序运行期间有机器执行。
也就是说,这些伪操作只在汇编过程中起作用,汇编结束,伪操作作用消失。

常量定义伪操作.equ
语法格式:
.equ symbol,expr
其中:
symbol 为要指定的名称,它可以是以前定义过的符号;
expr 表示数字常量或程序中的标号。
示例:
.equ TEST_NUM,#0x20

声明全局常量伪操作.global或.globl
语法格式:
.global symbol
.globl symbol
其中:
symbol为要声明的全局变量名称
示例:
.global start
.globl start

声明外部常量伪操作.extern
语法格式:
.extern symbol
其中
symbol为要声明的外部变量名称
示例:
.extern main

字节定义.byte
语法格式.byte expr{,expr}…
其中:
expr数字表达式或程序中的标号。
示例:
.byte 20

半字定义.hword或.short
语法格式:
.hword expr {,expr}……
.short expr {,expr}…….
其中:
expr数字表达式或程序中的标号

字定义.word或.int或.long
语法格式:
.word expr{,expr}…
.int expr {,expr}……
.long expr {,expr}…….
其中:
expr数字表达式或程序中的标号

字符串定义.ascii和.asciz或.string
语法格式:
.ascii expr{,expr}…
.asciz expr {,expr}……
.string expr {,expr}…….
其中:
expr 表示字符串。
示例:
str:
.ascii “test\0”
str1:
.asciz “tarena”
.ascii定义字符串,需要人为添加结束符
.asciz和.string定义字符串,是不需要添加结束符

固定填充字节内存单元定义.space或.skip
语法格式:
.space size{,value}
.skip size{,value}
其中:
size 所分配的字节数
示例:
yy:
.space 1024
从yy开始,分配了1024个字节,以0填充

如何使用汇编代码实现两个字符串的比较?
/*****************************************/
汇编语言与c语言混合编程
1.C语言中如何调用汇编语言实现的函数
这里写图片描述

extern void my_strcmp(char *d/*r0*/,const char *s/*r1*/);main.c:int  main(void){    char buf[256];    uart0_gets(buf);    my_strcmp(buf,"ledon");    //此时调用的my_strcmp函数就是汇编实现的字符串比较函数}

注意
(1)汇编函数名字声明为全局标号.global my_strcmp
(2)c程序若要调用这个函数,需要声明该函数原型
extern void my_strcmp(char d/*r0/,const char s/*r1/);
(3)按照c语言的方式调用该函数

2.C语言中如何使用汇编语言定义的变量

    .data    .global yyyy:    .word 0x100

(1)汇编中将该变量声明为全局变量
(2)在c语言中声明为外部标号
extern int yy;
(3)按照c的方式使用该变量

3.汇编语言中调用c的函数

int add(int a,int b,int c,int d){    return (a+b+c+d);}

(1)c程序中该函数定义为全局,不能加static
(2)汇编程序中声明为外部标号

    .extern add

(3)按照汇编的方式调用

    mov r0,#1@a=1    mov r1,#2@b=2    mov r2,#3@c=3    mov r3,#4@d=4    bl add@CPU将bl指令下一条指令地址给lr,PC    cmp r0,#0 @r0 = r0 + r1 + r2 + r3

4.汇编语言中如何调用C中的变量

int a;

(1)c中变量声明为全局;
(2)汇编程序中声明变量为外部变量
.extern a
(3)按照汇编的方式使用

    ldr r0,=a    ldr r1,[r0]

被调用方:
将被调用方函数或变量都要定义为全局的
调用方:
声明函数原型和变量为外部标号
/////////////////////////////
混合编程:
参数传递(1)
开始四个字大小的参数直接使用r0,r1,r2,r3
如果超过4个参数则使用堆栈
////////////////////////////////////
c程序调用汇编函数
将用汇编实现的字符串比较函数替换掉用c实现的字符串比较函数
1.汇编函数(字符串比较函数)定义为全局标号
2.在c程序中将汇编函数的函数原型声明为extern
3.替换c函数,用汇编函数

///////////////////////////////////////////////////
C
1.清BSS段
2.调用main函数

arm-linux-ld -nostartfiles
/******************************/
异常处理:
异常模式:
SVC管理模式:复位,执行SWI指令
FIQ快速中断模式:发生高优先级的中断
IRQ中断模式:发生低优先级的中断
中止模式:
未定义模式:

异常:
1.复位异常,进入管理SVC模式
2.未定义指令异常,进入到未定义模式
3.软中断异常,执行SWI指令,进入管理SVC模式
4.预取指令异常,没有取到指定的指令,进入中止模式
5.数据中止异常,没有取到指定的数据,进入中止模式
6.中断,进入中断模式
7.快速中断,进入快速中断模式

如何处理异常:
异常发生,处理异常,CPU做:
1.拷贝CPSR到相应异常模式的SPSR,SPSR_mode=CRSP
2.设置适当的CPSR位:
(1)将处理器的状态改为ARM状态,CPSR的bit[5]=0
(2)改变处理器的工作模式,进入到相对应的异常模式,改CPSR的bit[4:0]到对应异常模式
(3)设置中断禁止位,进入相应的中断
3.保存返回地址到lr_mode=PC-4
4.设置PC为相应的异常向量的地址
5.处理异常
6.异常处理完毕,返回
这里写图片描述
优先级reset最高

软中断SWI

...sub r1,r1,#0x5swi 1 @发生软中断异常add r0,r0,#0x1bic r0,r0,#0xf0...

取指,解码,执行,在swi指令,第三个阶段,执行阶段,发生异常
1.SPSR_SVC = CPSR
2.改CPSR的T位,0
3.改CPSR的mode[4:0]位,改到SVC管理模式
4.禁止中断位
5.lr=PC-4(PC=bic)=add
6.PC=处理异常的地址
7.处理异常
8.异常处理完毕,异常返回,movs pc,lr CPSR=SPSR

未定义指令异常:

...sub r1,r1,#0x5abc #3 @未定义指令add r0,r0,#0x1bic r0,r0,#0xf0...

取指,解码,执行,当abc指令进入执行阶段,发生异常
1.SPSR_未定义 = CPSR
2.改CPSR的T位,0
3.改CPSR的mode[4:0]位,改到未定义模式
4.禁止中断位
5.lr=PC-4(PC=bic)=add
6.PC=处理异常的地址
7.处理未定义异常
8.异常处理完毕,异常返回,movs pc,lr CPSR=SPSR

FIQ IRQ

...sub r1,r1,#0x5add r0,r0,#0x1bic r0,r0,#0xf0cmp r0,r1...

当执行到sub指令时,来了中断,虽然中断来了,sub指令执行完毕,响应中断异常
PC = cmp
lr = pc - 4 = bic
异常返回时,执行add指令,subs pc,lr,#4 CPSR = SPSR

预取指令异常

...sub r1,r1,#0x5add r0,r0,#0x1bic r0,r0,#0xf0cmp r0,r1...

1.当sub取指,根本没有取到,直到执行阶段,发生异常
2.lr=pc-4=add pc=bic
3.异常返回:
再次取指sub指令,subs pc,lr,#4 CPSR=SPSR

数据异常返回:

...ldr r0,[r2] @将r2地址里面的值加载到r0(取指,解码,执行,访存,回写)sub r1,r1,#0x5add r0,r0,#0x1bic r0,r0,#0xf0cmp r0,r1...

1.在ldr指令的访存阶段发生异常,PC=bic
2.lr=pc-4=add
3.异常返回:sbus pc,lr,#8 cpsr=spsr
这里写图片描述

小结:
异常的返回:
swi软中断异常
未定义指令异常
中断
快速中断
预取指令
数据异常
1.什么时候发生的异常
执行阶段PC和当前相差8(SWI,未定义,预取指令)
执行完毕阶段 PC和当前相差12(中断,快速中断)
访存阶段PC和当前相差12(数据异常)
确定当前的PC值
2.CPU:自动的,lr=pc-4
3.异常处理完毕,返回时,执行的指令是哪条
(1)重新执行发生异常的指令(预取指令,数据异常)
(2)执行发生异常的下一条指令

软中断
这里写图片描述
系统执行代码,执行SWI 0x01指令,在该指令的执行阶段,发生软中断异常
CPU:
1.备份CPSR,SPSR_SVC=CPSR
2.修改CPSR
(1)改状态,ARM状态,CPSR的bit[5]=0
(2)改模式,SVC管理模式,CPSR的bit[4:0]=10011
(3)改中断位
3.保存返回地址lr_svc=PC-4
4.修改PC为异常向量表中对应的地址PC=0x8,对应指令:
ldr pc,swi_hdl
5.swi_hdl就是SWI指令的异常处理程序,在此程序中,可以调用C语言编写的较为复杂的处理过程。(汇编调用C函数)
6.当c函数处理完毕之后,返回汇编swi_hdl,再做最后的异常返回
7.movs pc,lr @ CPSR=SPSR
8.接下去继续执行swi指令后的下一条指令

具体实现:
shell#s1 点灯
shell#s2 灭灯

0 0