标签:
嵌入式系统实验汇编指令keiluvisionarm7tdmi实验报告 |
分类: 实验报告 |
实验一:汇编指令实验
一、实验目的
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
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)
else
|
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))
else
|
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))
else
|
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 |