3.5 实验步骤
①创建工程,添加源文件,编辑源代码
启动ADS1.2,使用ARM Executable Image工程模板建立一个工程Project3。建立汇编源文件TEST3.S,编写实验程序,然后添加到工程中。 ②链接选项配置
设置工程链接地址RO Base为0x40000000,RW Base 0x40003000,设置调试入口地址Image entry point为0x40000000。
③编译链接工程
选择Project-〉Debug,启动AXD进行软件仿真调试。打开寄存器窗口(Processor Registers),选择Current项监视各寄存器的值。
④调试工程
单步运行程序,观察寄存器值的变化。
? R8 = R3 = X + Y,单步运行调试寄存器窗口如图3.1所示。
图3.1 单步调试运行界面
? R5 = 0x5FFFFFF8 – R8?8,单步运行调试寄存器窗口如图3.2所示。
图3.2 单步调试运行界面
3.6 实验参考程序
汇编指令实验2的参考程序见程序清单2.3。 程序清单2.3 汇编指令实验2参考程序 X EQU 11 ;定义X的值为11 Y EQU 8 ;定义Y的值为8
BIT23 EQU (1<<23) ;定义BIT23的值为0x00800000
AREA Example3,CODE,READONLY ;声明代码段Example3 ENTRY ;标识程序入口 CODE32 ;声明32位ARM指令 START ;使用MOV和ADD指令实现:R8 = R3 = X + Y MOV R0,#X ;X的值传入R0,X的值必须是8位图数据 MOV R1,#Y ;Y的值传入R0,Y的值必须是8位图数据 ADD R3,R0,R1 ;R3 = R0 + R1 = X + Y MOV R8,R3 ;将R3的值传入R8
;使用MOV、MVN和SUB指令实现:R5 = 0x5FFFFFF8 – R8?8 MVN R0,#0xA0000007 ;0xA0000007的反码为0x5FFFFFF8 SUB R5,R0,R8,LSL #3 ;R8左移3位,结果即是R8?8
;使用CMP指令判断(5?Y/2)>(2?X)吗?若大于,则R5 = R5 & 0xFFFF0000,否则R5 = R5 | 0x000000FF
MOV R0,#Y
ADD R0,R0,R0,LSL #2 ;计算R0 = Y + 4?Y = 5?Y
MOV R0,R0,LSR #1 ;计算R0 = 5?Y/2 MOV R1,#X
MOV R1,R1,LSL #1 ;计算R1 = 2 ? X
CMP R0,R1 ;比较R0和R1,即(5?Y/2)>(2?X)进行比较
LDRHI R2,=0xFFFF0000 ;若(5?Y/2)>(2?X),则R2 = 0xFFFF0000 ANDHI R5,R5,R2 ;若(5?Y/2)>(2?X),则R5 = R5&R2 ORRLS R5,R5,#0x000000ff ;若(5?Y/2)<=(2?X),则R5 = R5 |
0x000000ff
;使用TST指令测试R5的BIT23是否为1,若是则将BIT6位清0(使用BIC指令)
TST R5,#BIT23
BICNE R5,R5,#0x00000040 B START END
汇编指令实验3的参考程序见程序清单2.4。 功能:计算Xn
nX = X? X ? X ???X ,其中相乘的X的个数为n。先将X的值装入
R0和R1,使用寄存器R2进行计数,循环n-1次R0 = R0 ? R1,运算结果保存在R0中。(不考虑结果溢出问题)
注意:若n 为 0,则运算结果直接赋1;若n为1,则运算结果直接赋X。 实验过程
①建立工程,编辑源文件
启动ADS1.2,使用ARM Executable Image工程模板建立一个工程Project4 建立汇编源文件TEST4.S,编写实验程序,然后添加到工程中。 ②编译链接工程
配置工程链接地址RO Base为0x40000000,RW Base为0x40003000。设置调试入口地址Image entry point为0x40000000
③调试程序
选择Project-〉Debug,启动AXD进行软件仿真调试。
打开寄存器窗口(Processor Registers),选择Current项监视寄存器R0、R1、R13(SP)和R14(LR)的值。
打开存储器观察窗口(Memory)设置观察地址为0x40003EA0,显示方式Size为32Bit,监视从0x40003F00起始的满递减堆栈区。
单步运行程序,跟踪程序执行的流程,观察寄存器值的变化和堆栈区的数据变化,判断执行结果是否正确。
调试程序时,更改参数X和n来测试程序,观察是否得到正确的结果。例如,先复位程序(选择File-〉Reload Current Image),接着单步执行到 “BL POW”
指令,在寄存器窗口中将R0和R1的值进行修改,然后继续运行程序。
说明:双击寄存器窗口的寄存器,即可修改寄存器的值。输入的数据可以是十进制数,例如136和198),也可以是十进制数(例如0x123和0xF0),输入数据后回车确定。
程序清单2.4 汇编指令实验3参考程序 文件名:TEST4.S 所在工程名:Project4
;文件名:TEST4.S
;功能:计算X的n次方的值 ;说明:X和n均为无符号整数
X EQU 9 ;定义X的值为9 n EQU 8 ;定义Y的值为8
AREA Example4,CODE,READONLY ;声明代码段Example4 ENTRY ;标识程序入口 CODE32 ;声明32位ARM指令 START LDR SP,=0x40003F00 ;设置堆栈(满递减堆栈,使用
STMFD/LMDFD指令)
LDR R0,=X LDR R1,=n
BL POW ;调用子程序POW,返回值为R0
HALT B HALT
;子程序:POW ;功能:整数乘方运算 ;入口参数:R0 底数 R1 指数 ;出口参数 R0 运算结果 ;占用资源:R0、R1
;说明:本子程序不考虑溢出问题
POW STMFD SP!,{R1-R12,LR} ;寄存器入栈保护
MOVS R2,R1 ;将指数值复制到R2,并影响条件标志
MOVEQ R0,#1 ;若指数为0,则设置R0 = 1 BEQ POW_END ;若指数为0,则返回
CMP R2,#1
BEQ POW_END ;若指数为1,则返回(此时R0没有被更改)
MOV R1,R0 ;设置DO_MUL子程序的入口参数R0和R1 SUB R2,R2,#1 ;计数器R2 = 指数值减1
POW_L1 BL DO_MUL ;调用DO_MUL子程序,R0 = R1 ? R0 SUBS R2,R2,#1 ;每循环一次,计数器R2减1
BNE POW_L1 ;若计数器R2不为0,跳转到POW_L1
POW_END LDMFD SP!,{R1-R12,PC} ;寄存器出栈,返回
;子程序:DO_MUL ;功能:32位乘法运算 ;入口参数:R0 乘数 R1 被乘数 ;出口参数:R0 计算结果 ;占用资源:R0、R1
;说明:本子程序不会破坏R1
DO_MUL MUL R0,R1,R0 ;R0 = R1 ? R0 MOV PC,LR ;返回 END
3.7 思考
(1)指令“MOV R0,#0x12345678”是否正确?为什么?
(2)将参考程序中应用CMP指令的代码功能改为:若(5?Y/2)>(2?X),则R5 = R5 | 0x000000FF, 否则R5 = R5 & 0xFFFF0000,程序应如何修改?
(3)更改参考程序的X值为200,Y值为163,单步运行程序,每执行一步程序的结果是多少?
(4)如何实现64位加法运算(R6、R5)= (R6、R5) + (R3、R2)?(提示:使用ADC指令。)