实验一:汇编指令实验

一、实验目的

1、了解 Keil uVision

集成开发环境及软件仿真功能使用。

2、掌握 ARM7TDMI

汇编指令的用法,并能编写简单的汇编程序。

3、掌握指令的条件执行和使用 LDR/STR

指令完成存储器的访问。

4、掌握基本的汇编程序调试。

二、实验设备

1、硬件:PC 机一台

2、软件:WindowsXP 系统,Keil uVision 4.0

集成开发环境

三、实验内容

(1)使用 LDR 指令读取 0x40000100

地址上的数据,将数据加 1。若结果小于 10,则使用 STR 指令把结果写回原地址;若结果大于等于 10,则把 0

写回原地址。

(2)使用 Keil uVision

软件仿真,单步、全速运行程序,设置断点,打开寄存器窗口监视 R0 和 R1 的值,打开存储器观察窗口监视 0x40000100

地址上

的值。

四、实验预习要求

(1)学习 ARM 指令系统的内容,重点掌握 LDR/STR

指令和指令条件执行;

(2)查阅 Keil uVision

软件的介绍,了解软件的功能和操作方法。

五、实验步骤

(1)启动 Keil uVision,新建一个工程

ex01。

(2)建立汇编源文件 ex01.s,

编写实验程序,然后添加到工程中。

(3)设置工程选项,存储器映射。

(4)编译链接工程。

(5)进行软件仿真调试。

六、实验程序

程序清单 1.1 汇编指令实验程序

COUNT EQU 0X40000100

;定义一个变量,地址为0x40000100

AREA RESET, CODE, READONLY

;声明代码段RESET

ENTRY ;表示程序入口

CODE32 ;声明32位ARM指令

START LDR R1,=COUNT ;R1 ←

COUNT

MOV R0,#0 ;R0 ← 0

STR R0,[R1] ;[R1] ← R0,即设置COUNT

为0

LOOP LDR R1,=COUNT

LDR R0,[R1] ;R0 ← [R1]

ADD R0,R0,#1 ;R0 ← R0 +

1

CMP R0,#10

;R0与10比较,影响条件码标志

MOVHS R0,#0 ;若R0 >=

10, 则此指令执行,即R0 ← 0

STR R0,[R1] ;[R1] ←

R0,即保存COUNT

B LOOP

END

七、实验现象

在每次循环前设置断点,全速运行,在第一次循环开始时,R0、0x40000010字内容都是0,在每次循环中加1,并将结果写回0x40000010地址。如此往复至0x40000010内容为10,将0装入0x40000010地址,并继续循环。

八、思考题

(1)若使用 LDRB/STRB

代替程序清单中的所有加载/存储指令(LDR/STR),程序会得到正确的执行吗?

答:使用LDRB/STRB

代替程序清单中的所有加载/存储指令(LDR/STR)后程序如下:

COUNT EQU 0X40000100

AREA RESET, CODE,

READONLY

ENTRY

CODE32

START LDR R1,=COUNT

MOV R0,#0

STRB R0,[R1]

LOOP

LDR R1,=COUNT

LDRB R0,[R1]

ADD R0,R0,#1

CMP R0,#10

MOVHS R0,#0

STRB R0,[R1]

B LOOP

END

程序先把0放入寄存器R0,然后把R0的最低字节放入R1所指向的地址中,即0,然后又把R1所指向的地址中的最低字节加载到寄存器R0,将R0加1,当R0≥10时,将R0清零,然后把R0的内容写到寄存器R1所指向的地址中,循环执行。

所以本程序从开始,用于寄存器和内存交换的R0、[R1],其交换数据在0—10之间,把数据传输指令LDR/STR改为LDRB/STRB后,交换数据仍在0—10之间,只传输最后一个字节足够。

即用 LDRB/STRB 代替程序清单中的所有加载/存储指令(LDR/STR),程序可以得到正确的执行。

(2)LDR 伪指令与 LDR

加载指令的功能和应用有何区别,举例说明? (提示:LDR 伪指令的形式为"LDR Rn,=expr"。 )

答:加载指令LDR指令格式:LDR{cond}{T}

Rd,

功能是加载指定地址上的数据(字),放入Rd中。T为可选后缀,若指令有T,那么即使处理器是在特权模式下,存储系统也将访问看成是处理器在用户模式下。LDR的寻址方式很灵活,有两部分组成,一部分为一个基址寄存器,可以为任何一个通用寄存器,另一部分为一个地址偏移量,可以是立即数、寄存器、寄存器与一位常数。

例如:

LDR R1,[R0,#-0x12]

LDR R1,[R0,-R2]

LDR R1,[R0,-R2,LSL #2]

伪指令LDR指令格式: LDR{cond}

register,=expr/label-expr

指令功能:LDR伪指令用于加载32位的立即数或一个地址值到指定寄存器。在汇编编译源程序时,LDR伪指令被编译器替换成一条合适的指令。若加载的常数未超出MOV或MVN

的范围,则使用这两条指令代替LDR指令,否则汇编器将常量放入文字池,并使用一条程序相对偏移的LDR伪指令从文字池读出常量。

例如:

LDR R0,=0x12345678

LDR R0,=DATA_BUF+60

两者最主要的区别是:LDR指令用于将内存中的数据字加载到目标寄存器,而LDR伪指令用于将立即数或地址加载到目标寄存器,即LDR伪指令加载的是常数。另外,LDR指令有丰富的寻址方式,还可以有T后缀,但是伪指令就没有这么多寻址方式,也没有T后缀。

(3)LDR/STR

指令的前索引偏移指令如何编写?指令是怎样操作的?

答:

LDR/STR的前索引偏移是指在数据传送之前,将偏移量加到Rn(第一个操作数的寄存器)中,其结果作为传送数据的存储地址。若使用后缀"!",则结果写回到Rn中,且Rn的值不允许为R15。

例如:

LDR Rd,[Rn,#0x04]

LDR R1,[R0,-R2,LSL #2]

写前索引偏移指令,要把第一个操作数寄存器和偏移量用"[

]"括起来,第一个操作数作为基址,后面的作为偏移量,将两者相加后得到的地址中的内容加载到目的寄存器中去。因此,常用来处理数组等结构,如:LDR

R1,[R0,-R2,LSL #2]。

九、选作内容

使用

ARM 汇编指令实现 if 条件执行。

答:若果if语句中判断的条件只有一个,用CMP和ARM的条件执行就可以实现,如(假设a和b分别在寄存器R0、R1中):

C语言

ARM汇编语言

if(a>b)

a++;

else

b++;

CMP R0,R1

ADDHI R0,R0,#1

ADDLS R1,R1,#1

如果在if条件语句中逻辑表达式是多个条件的逻辑组合,则需要用CMP配合分支指令实现if,如(假设a和b分别在寄存器R0、R1中):

C语言

ARM汇编语言

if((a!=b)&&(b==20))

a=a+b;

else

a=a-b;

CMP R0,#10

BEQ Else

CMPNE R1,#20

BNE Else

ADD R0,R0,R1

B Exit

Else SUB R0,R0,R1

Exit ;其他指令

if((a!=b)||(b==20))

a=a+b;

else

a=a-b;

CMP R0,#10

BNE If

CMPEQ R1,#20

BEQ If

SUB R0,R0,R1

B Exit

If ADD R0,R0,R1

Exit ;其他指令

使用

ARM 汇编指令实现 for 循环结构。

使用for循环时,首先要初始化,申请局部变量,对应于ARM中堆栈的变化。进入循环体后,先判断条件,不如何则跳出,符合则执行,然后自增或自减,循环,例如:

C语言

ARM汇编语言

for(i=0;i<100;i++)

{

a=a+b;

}

EOR R0,R0,R0

Loop CMP R0,#100

BHS Exit

ADD R1,R1,R2

ADD R0,R0,#1

B Loop

Exit ;其他指令

使用

ARM 汇编指令实现 while 循环结构。

while循环结构先判断条件,然后才执行,用ARM汇编语言实现就是先判断条件,不符合则跳转,符合则执行,最后循环,如:

C语言

ARM汇编语言

while(a=b)

{

执行体;

}

Loop CMP R0,R1

BNE Exit

;执行体

B Loop

Exit ;其他指令块

使用

ARM 汇编指令实现 do…while 循环结构。

do-while循环结构先执行,然后判断条件,用ARM汇编语言实现即先执行,然后比较判断条件,不符合条件则退出,符合则循环执行,如:

C语言

ARM汇编语言

do

{

执行体;

} while(a=b);

Loop ;执行体

CMP R0,R1

BEQ Loop