实验一 ARM汇编指令基础及多字节加减法
一、实验目的
? 初步学会使用Embest IDE for ARM 开发环境及ARM软件模拟器; ? 通过实验掌握简单ARM汇编指令的使用方法。 二、实验原理
ARM处理器共有37个寄存器:
? 31个通用寄存器,包括程序计数器(PC)。这些寄存器都是32位。 ? 6个状态寄存器。这些寄存器也是32位,但只使用了其中的12位。
1. ARM通用寄存器
通用寄存器(R0~R15)可分为3类。 1) 不分组寄存器R0~R7
R0~R7是不分组寄存器。在所有处理器模式下,它们都能被访问。它们是真正的通用寄存器,没有体系结构所隐含的特殊用途。
2) 分组寄存器R8~R14
R8~R14是分组寄存器。被访问的物理寄存器取决于当前的处理器模式。若要访问特定的物理寄存器而不依赖当前的处理器模式,则要使用规定的名字。
寄存器R8~R12各有两组物理寄存器:一组为FIQ模式,另一组为除了FIQ模式以外的所有模式。R8~R12没有任何指定的特殊用途。只是使用R8~R12来简单地处理中断。寄存器R13和寄存器R14各有6个分组的物理寄存器,1个用于用户模式和系统模式,其他5个分别用于5种异常模式。R13通常用作堆栈指针,称作SP。每种异常模式都有自己的R13。R14用作子程序链接寄存器,也称作LR。
3) 程序计数器R15
寄存器R15用作程序计数器(PC)。
本实验中,ARM核工作在用户模式,R0~R15可用。 2. 存储器格式
ARM体系结构可以用两种方法存储字数据,分别称为大端格式和小端格式。 1) 大端格式
在这种格式中,字数据的高位字节存储在低地址中,而字数据的低位字节存 放在高地址中,如下所示:
高地址 31 23 22 16 15 8 7 0 字地址
8 9 10 11 8
4 5 6 7 4
0 1 2 3 0
低地址
2) 小端格式
在这种格式中,字数据的高位字节存储在高地址中,而字数据的低位字节存 放在低地址中,如下所示:
高地址 31 23 22 16 15 8 7 0 字地址
11 10 9 8 8
7 6 5 4 4
3 2 1 0 0
低地址
3. 算术逻辑运算
ARM处理器具有很强的算术逻辑运算功能,算术指令可以实现32位有符号数和无符
号数的加法和减法操作。其语法为:
ADC ADD SBC SUB RSB RSC 32位带进位加法 32位加法 带借位的减法 32位减法 32位逆向减法 带借位的32位逆向减法 Rd=Rn+N+carry Rd=Rn+N Rd=Rn-N-!(carry flag) Rd=Rn-N Rd=N-Rn Rd=N-Rn-!(carry flag) 注:N是桶形移位器操作的结果 从上表可以看出,ADD和SUB是最简单的加减运算。
ADC和SBC是带进位标志的加减运算,对于SBC,若进位标志为0,则结果减1。 RSB是反减,即用第2操作数减去源操作数,由于第2操作数可选的范围宽,故这条指令很有用。
RSC是带进位标志反减,若进位标志为0,则结果减1。 在ARM指令集中,通过设置S位(第20位),可以直接控制指令的执行是否影响条件码。当S位为0时,条件码不改变;当S位为1时(且Rd不是R15(PC)),条件码改变。 4.GNU基础知识
Embest IDE集成了GNU汇编器as、编译器gcc和链接器ld。因此,编写程序要符合GNU的语法和规则。这里简单介绍几点基本知识:
? 程序默认入口点为“_start”,代码段默认起始地址为0x8000 ? 常用伪操作符 1) .equ
为数字常量、基于寄存器的值和程序标号定义一个字符名称。 2) .global及.globl
声明一个符号可以被其他文件引用,相当于声明了一个全局变量。 3) .text
将操作符开始的代码编译到代码段或代码段子段(Subsection)。 4) .end
标记汇编文件的结束行。 三、实验内容
? 熟悉开发环境的使用并使用ldr/str,mov等指令访问寄存器或存储单元。 ? 使用add/sub/adc/sbc等指令,完成基本数学运算。 ? 完成两个128位无符号整数加法程序。
? 运行Embest IDE集成开发环境,将下面两段参考程序分别编辑输入,生成目标代
码,设置调试模块,下载目标代码到软件仿真器。
四、实验步骤
1. 打开memory窗口,观察地址0x8000与地址0x1000周围的内容。 2. 单步执行程序并观察和记录寄存器与memory的值变化。
3. 结合实验内容和相关资料,观察程序运行,通过实验加深理解ARM指令的使用。 五、实验参考程序
1. 实验参考程序一:
.equ x, 45 /* 定义变量x,并赋值为45*/ .equ y, 64 /* 定义变量y,并赋值为64*/
.equ stack_top, 0x1000 /* 定义栈顶0x1000*/ .global _start .text
_start: /*程序代码开始标志*/ MOV sp, #stack_top MOV r0, #x /* x的值放入R0 */ STR r0, [sp] /* R0的值保存到堆栈*/ MOV r0, #y /* y的值放入R0*/ LDR r1, [sp] /* 取堆栈中的数到R1*/ ADD r0, r0, r1 STR r0, [sp] stop:
B stop /*程序结束,进入死循环*/ .end
2. 实验参考程序二: .global _start .text .arm
_start: /*程序代码开始标志*/ MOV r0, #0x1 /* 对寄存器赋初值*/ MOV r1, #0x2 MOV r2, #0x3 MOV r3, #0x4 MOV r4, #0x100A MOV r5, #0x1000B MOV r6, #0x10000C MOV r7, #0x100000D
ADDS r0, r0, r4 /* 低32位相加并影响标志位*/ ADCS r1, r1, r5 /* 32位相加再加上进位值*/ ADCS r2, r2, r6 ADCS r3, r3, r7 stop:
B stop /*程序结束,进入死循环*/ .end
六、思考题:
完成两个128位无符号整数减法程序。
相关推荐: