实验六 ARM数据加载与存储指令实验

更新时间:2023-03-15 03:34:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

实验六 ARM数据加载与存储指令实验

一、实验目的

1、熟悉教学ADS集成开发环境,

2、懂得各种ARM寻址方式,并能自己动手写一些简单小程序。 3、能够运行程序并进行简单分析 二、实验环境

硬件:PC机一台。

软件:Windows98/XP/2000系统,ADS集成开发环境。 三、预备知识

LDR 和STR——用于字和无符号字节 指令格式:

LDR/STR{cond}{T} Rd,<地址> LDR/STR{cond}B{T} Rd,<地址> 指令LDR{cond}{T} Rd,<地址>,加载指定地址的字数据到Rd中;指令STR{cond}{T} Rd,<地址>,存储Rd中的字数据到指定的地址单元中。LDR{cond}B{T} Rd,<地址>指令 加载指定地址的字节数据到Rd的的最低字节中(Rd的高24位清零);STR{cond}B{T} Rd, <地址>指令存储Rd中的最低字节数据到指定的地址单元中。T为可选后缀,若有T,那么即使处理器是在特权模式下,存储系统也将访问看成处理器是在用户模式下,T 在用户模式下无效,不能与前索引偏移一起使用T。地址部分可用的形式有4种:

零偏移(zero offset) [Rn],Rn 的值作为传送数据的地址。如: LDR R0,[R1];

前索引偏移(pre-indexed offset) [Rn,Flexoffset]{!} 在数据传送之前,将偏移量Flexoffset 加到Rn 中。其结果作为传送数据的存储器地址。若使用后缀“!”,则结果写回到Rn 中,35且Rn 不允许是R15,如:

LDRB R0,[R1,#8] LDR R0,[R1,#8]!

程序相对偏移(program relative) label(label 必须是在当前指令的土4KB 范围内) 。 程序相对偏移是前索引形式的另一种版本。从PC 计算偏移量,并将PC 作为Rn 生成 前索引指令,不能使用后缀“!”,如:

LDR R0,place ;place 地址装入R0

后索引偏移(post-indexed offset) [Rn],Flexoffset。在数据传送后,将偏移量Flexoffset 加到Rn 中,结果写回到Rn,Rn 不允许是R15,如:

LDR R0,[R1],R2,LSL#2 ;将存储器地址为R1 的字数据读入寄存器R0,并将新地址R1+R2×4 写入R1。 四、实验内容

(1)分析单寄存器操作,并学会简化给出的代码同时实现相同的效果;

(2)使用多寄存器操作指令:LDMIA、STMIA实验上面单寄存器操作所实现的功能; (3)给出实验所提供的堆栈操作的代码执行过程的详细分析;

(4)根据给出的用C写成的数码管显示,用相应的汇编实现同样功能。 五、实验程序

(1)单寄存器操作代码如下: AREA Lab1, CODE ENTRY

START ADR R1,SRC ADR R2,DST COPY LDR R0,[R1] STR R0,[R2] ADD R1,R1,#0x4 ADD R2,R2,#0x4 LDR R0,[R1] STR R0,[R2] ADD R1,R1,#0x4 ADD R2,R2,#0x4 LDR R0,[R1] STR R0,[R2] STOP B STOP

SRC DCB \ ALIGN

DST DCB \ END

对以上这段用单寄存器操作实现的代码的分析:功能实现的就是将“one small!”穿送到“three big!”所在的内存空间,不过因为只是通过单寄存器来实现传送操作的,显得有些繁琐,这里是加一次数据,在分别给2个寄存器加地址,一共写了3段相同的代码才完成,下面我对这段不断重复的代码:LDR R0,[R1];STR R0,[R2];ADD R1,R1,#0x4;ADD R2,R2,#0x4加以修改,使用两条指令实现与上面代码相同的功能操作:简化如下:指令一:LDR R0,[R1],#0x4;指令二:STR R0,[R2],#0x4。

(2)多寄存器操作实验

尽管前一个实验在完成后,对繁琐的蛋寄存器操作加以简化,提高了一点效率,但是这是在寄存器之间传递数据,那么就有了更加高效的方法来实现相同的功能。那就是使用多寄存器操作指令:LDMIA、STMIA实验上面代码的功能。下面我给出了给出完整的代码实现:

AREA Lab1, CODE ENTRY START ADR R1,SRC ADR R2,DST COPY LDMIA R1!,{R3,R4,R5} STMIA R2!,{R3,R4,R5} STOP B STOP

SRC DCB \ ALIGN

DST DCB \ END

对以上这段用多寄存器实现数据的传递,要说的是只有在寄存器直接的数据传递才能使用多寄存器操作,在这里SRC,DST分别代码2组数据的所在的首地址,SRC将“one small!”地址赋值给了寄存器R1,DST将“three big!”地址赋值给了寄存器R2,然后通过多寄存器操作“LDMIA R1!,{R3,R4,R5}”将“one small!”暂时存放在寄存器R3,R4,R5中,在通过指令“STMIA R2!,{R3,R4,R5}”将暂存的数据传给DST所代表的地址内存中讲原有的数据“three big!”覆盖。

(3)堆栈操作实验 AREA Lab2,CODE ENTRY START LDR SP,=NUM LDMFD SP!,{R0-R4} ADD R4,R0,R1 ADD R4,R4,R2 ADD R4,R4,R3 MOV R4,R4,LSR #2 STR R4,[SP] STOP B STOP AREA Dblock,DATA

NUM DCD 0x12,0x34,0x56,0x78 END

给出上面代码的详细执行过程:这段堆栈操作实现的是将内存中的原有的的4个数据相加,再逻辑右移2位并将最后的结果存入到与之相邻的后一个存储空间。具体分析如下:NUM代表这组数的内存首地址,因为是堆栈操作说有用到sp,将NUM所代表的地址送至sp中,即sp=0x8024,然后执行出栈操作,遵循高地址的数传给编号打的寄存器,这样R0=0x12,R1=0x34,R2=0x56,R3=0x78,在出栈的同时,sp的指向也随之变化sp=0x8038。然后几个简单的加操作件内存中的的那组数据相加,再将逻辑右移2位后的值0x45传入sp现在所指向的内存空间。

(4)数码管操作实验

使用汇编语言实验下面C语言代码的功能:

****************************************************************************/ /*文件名称: LEDSEG7.C */ /*实验现象: 数码管依次显示出0、1,2、??9、a、b、C、d、E、F */ /****************************************************************************/ #define U8 unsigned char

unsigned char seg7table[16] = {

/* 0 1 2 3 4 5 6 7*/ 0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8,

/* 8 9 A B C D E F*/ 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e, };

void Delay(int time);

/****************************************************************************/ /* 函数说明: JXARM9-2410 7段构共阳数码管测试 */

/* 功能描述: 依次在7段数码管上显示0123456789ABCDEF */ /* 返回代码: 无 */ /* 参数说明: 无 */ /****************************************************************************/ void Main(void) { int i; *((U8*) 0x10000006) = 0x00; for( ; ; ) { /* 数码管从0到F依次将字符显示出来 */ for(i=0;i<0x10;i++) { /* 查表并输出数据 */ *((U8*) 0x10000004) = seg7table[i]; Delay (100000); } /* 数码管从F到0依次将字符显示出来 */ for(i=0xf;i>=0x0;i--) { /* 查表并输出数据 */ *((U8*) 0x10000004) = seg7table[i]; Delay (100000); } } }

/****************************************************************************/ /* Function name : 循环延时子程序 */ /* Description : 循环 'time' 次 */ /* Return type :void */ /* Argument : 循环延时计数器 */ /****************************************************************************/ void Delay(int time) { int i; int delayLoopCount=1000; for(;time>0;time--); for(i=0;i

实现相同功能的汇编程序如下: LDR R0, =#0x10000006 LDR R1, =#0x10000004 MOV R0,#0X00 LDR R2, =NUM START LDR R1,[R2]! MOV r7,#0XFF DELAY

NUM DCD 0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e,

六、实验总结

通过本次实验,我对ADS开发环境的使用进一步熟练,在编写程序的过程中加深了对相关汇编指令的理解,对单字节传送指令的运用更加得心应手,我学到了很多,最重要的是在这次实验中纠正了我犯的一个错误让我牢记:批数据传送指令STM和LDM只能用在寄存器之间的数据传送,但是在讲c写的数码显示的代码改成汇编是遇到了很大的困难。

本文来源:https://www.bwwdw.com/article/zs3t.html

Top