arm_day11

来源:互联网 发布:消防知识知多少 200字 编辑:程序博客网 时间:2024/05/07 11:09

回顾:

--------------------------------------------------------------------------------------

指令集

(1)跳转指令:B BL BX 修改PC寄存器

(2)数据处理指令:

   1.数据传送

   2.算术运算

   3.位运算

   4.比较测试

操作码{条件}S   目标寄存器,第一源操作数,第二源操作数

 

(3)加载存储指令

单寄存器

LDR    Rd,<地址模式>

LDRB   Rd,<地址模式>

基址+偏移量(立即数,寄存器,寄存器移位)

LDRH   Rd,<地址模式>

LDRSH  Rd,<地址模式>

LDRSB  Rd,<地址模式>

基址+偏移量(立即数,寄存器)

STR    Rd,<地址模式>

STRH   Rd,<地址模式>

STRB   Rd,<地址模式>

(4)多寄存器

LDM    Rb! ,{R0, R1,R2}

STM

IA

IB

DA

DB都是指的如何操作地址的

 

(5)栈

满减栈

Push  STMDB STMFD

Pop   LDMIA  LDMFD

 

MRS 读CPSR,SPSR

MSR 写CPSR,SPSR

 

(6)伪指令:

ADR

ADRL

 

LDR

LDR  PC,label

 

label:

.word  0x12345678

 

LDR  R0,=label

LDR  PC , [R0]

 

label:

.word  0x12345678

 

 

NOP

--------------------------------------------------------------------------------------

Day11

伪操作

main:   mov r1, r0  @主程序入口

 

 test.s示例

     .text                      @指定代码放到.text段

     .global  do_sub             @声明全局标号

 

do_sub:

     sub   r0, r0, r1              @两个数相减

     mov  pc, lr               @子程序返回

     .end

 

伪操作(derective

    汇编语言程序里的一些特殊助记符为编程方便,完成一些辅助功能的操作。

    在对汇编源程序进行汇编过程中由汇编程序处理,而不是在程序运行期间由机器执行.

    也就是说,这些伪操作只在汇编过程中起作用,汇编结束,伪操作作用消失。

 

(1)常量定义伪操作.equ

语法格式:

.equ   symbol,  expr

其中:

symbol   为要指定的名称,它可以是以前定义过的符号;

expr       表示数字常量或程序中的标号。

示例

.equ    TEST_NUM, #0x20

 

(2)声明全局常量伪操作.global或.globl

语法格式:

.global symbol

.globl symbol

其中:

symbol  为要声明的全局变量名称

示例

.global    start

.globl     start

 

(3)声明外部常量伪操作.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语言中如何调用汇编语言实现的函数

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

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

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

 

1.C语言中如何调用汇编语言实现的函数

      .text

     .code 32

      .global  my_strcmp

my_strcmp:

   ldrb r2,[r1],#1

   ldrb r3,[r0],#1

   cmp r2, #0

   beq cmd_end

   ….

cmd_end:

   ….

   bx  lr

  

     

extern  void my_strcmp(char  *d, constchar  *s);

                            r0          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, constchar  *s);

                                r0          r1

3.按照C语言的方式调用该函数

 

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

   .data

  .global yy

yy:

      .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

mov   r1, #2  ->b

mov   r2, #3  ->c

mov   r3, #4  ->d

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]

 

被调用方:

将被调用函数或变量都要定义为全局的

调用方:

声明函数原型和变量为外部标号

 

C程序调用汇编函数

将用汇编实现的字符串比较函数替换掉用C实现的字符串比较函数

1.汇编函数(字符串比较函数)定义为全局标号

2.在C程序中将该汇编函数的函数原型声明为extern

3.替换C函数,用汇编函数

 

汇编语言C语言

r0 r1 r2 r3

 

a_strcmp.s源文件

 

a_strcmp(name,cmd_tbl[i].name)

           r0         r1

 

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=CPSR

2.设置适当的CPSR位:

  1.将处理器的状态改为ARM状态,CPSR的bit[5]=0

  2.改变处理器的工作模式,进入到相对应的异常模式,改CPSR的bit[4:0]到对应异常模式

  3.设置中断禁止位,禁止相应的中断

3.保存返回地址到lr_mode=PC-4

4.设置PC为相应的异常向量的地址

5.处理异常

6.异常处理完毕,返回

 

软中断SWI

…….

sub  r1, r1, #0x5

swi  1         @发生软中断异常

add  r0, r0, #0x1

bic   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=0x8

7.处理异常

8.异常处理完毕,异常返回,movs  pc, lr   CPSR=SPSR

 

未定义指令异常

…….

sub  r1, r1, #0x5

abc  #3   @未定义指令

add  r0, r0, #0x1

bic   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, #0x5

add  r0, r0, #0x1

bic   r0,r0, #0xF0

cmp  r0,r1

……..

当执行到sub指令时,来了中断,虽然中断来了,sub指令执行完毕,发生中断异常

pc=cmp

lr =pc-4=bic

异常返回时,执行add指令,subs pc, lr, #4  CPSR=SPSR

 

预取指令异常

…….

sub  r1, r1, #0x5

add  r0, r0, #0x1

bic   r0, r0, #0xF0

cmp  r0,r1

……..

1.当sub取指,根本没有取到,直到执行阶段,发生异常

2.lr=pc-4   pc=bic

   =add

3.异常返回:

  再次取指sub指令,subs pc , lr , #4    CPSR=SPSR

 

数据异常返回

…….

ldr   r0, [r2] //取指,解码,执行,访存,回写

sub  r1, r1, #0x5

add  r0, r0, #0x1

bic   r0, r0, #0xF0

cmp  r0,r1

……..

1.在ldr指令的访存阶段发生异常,pc=bic

2.lr=pc-4=add

3.异常返回:subs  pc, lr, #8  cpsr=spsr

 

异常的返回

   swi软中断异常

   未定义指令异常

   中断

   快速中断

   预取指令

   数据异常

1.什么时候发生异常

  执行阶段        8(SWI,未定义,预取指令)

  执行完毕阶段   12(中断,快速中断)

  访存阶段       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

ftp://arm/day09/irq_uboot.rar

将irq_uboot.rar拷贝到共享目录中,在windows解压

cp   bss  swi  -rf

cd   swi

cp   /mnt/hgfs/1405/irq_uboot/irq_uboot/*   ./

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

0 0