做者:毛茏玮 / Saintgit
掘金:juejin.im/user/5aa1f8…github
GitHub :github.com/saint-000编程
test1.1ARM数据处理指令寻址方式实验和ARM内存访问指令寻址方式实验中代码以下:bash
经过调试能够发现知道代码中的数据传送指令MOV;算术运算指令-加法指令ADD和减法指令SUB;以及比较指令CMP等数据处理指令在寄存器的数值和地址的变化,初步了解ARM的寻址方式以及数据传送方式。函数
test1.2编程实现1+2+…+N 代码书写:ui
;功能:计算1+2+3+4+...+N
;说明;N>=0,当N=0时结果为0,当N=1时结果为1
N EQU 100 ;定义N的值100
AREA Examples,CODE,READONLY ;声明代码断Examples3
ENTRY ;标识程序入口
CODE32
ARM_CODE
LDR SP,=0X30003F00 ;设置堆栈指针
ADR R0,THUMB_CODE+1
BX R0 ;跳转并切换处理器状态
LTORG ;声明文字池
CODE16
THUMB_CODE
LDR R0,=N ;设置子程序SUM_N的入口参数
BL SUM_N ;调用子程序SUM_N
B THUMB_CODE
;SUM_N
;功能:计算1+2+3+......+N
;入口参数:R0 N的值
;出口参数:R0 运行结果
;占用资源:R0
;说明:当N=0时结果为0,当N=1时结果为1
;若运算溢出,结果为0
SUM_N
PUSH {R1-R7,LR} ;寄存器入栈保护
MOVS R2,R0 ;将n的值复制到R2,并影响相应条件标志
BEQ SUM_END ;若N=0,则返回,成当即返回
CMP R2,#1 ;比较R2是否为1
BEQ SUM_END ;若N=1,则返回,成当即返回
MOV R1,#1 ;初始化计数器R1=1 MOV R0,#0 ;初始化计数器R0=0
SUN_L1
ADD R0,R1 ;R0=R1+R0
BVS SUM_END ;溢出
CMP R1,R2 ;比较R1和n是否相等
BVS SUM_END ;相等,跳出循环,即加到n结束
ADD R1,#1 ;R1=R1+1;
B SUN_L1 ;跳转循环
SUM_ERR
MOV R0,#0 ;R0=0
SUM_END
MOV R8,R0 ;将结果保存在R8中
POP {R1-R7,PC} ;寄存器出栈,返回
END
复制代码
结果: 最终寄存器R8的读数为为0X000013BA,数值为十进制的5050,正好是从1加至100之和,因此成功实现该功能。spa
test1.3理解C和汇编,并用汇编程序实现字符串拷贝,并在C程序中调用该汇编程序。3d
在C程序中调用该汇编程序:指针
;文件名:main.c
;功能:完成字符串的拷贝
#include <stdio.h>
extern void strcopy(char *d ,char *s);
int main(void)
{
char *srcstr = "aaaa";
char dststr[] = "bbbb";
//printf("Before copying:\n"); //仿真调试时禁用printf语句
//printf(" %s %s\n",srcstr,dststr);
strcopy(dststr,srcstr);
//printf("After copying: \n");
//printf(" %s\n %s\n",srcstr,dststr);
return (0);
}
复制代码
在汇编程序中:
;文件名:TEST.S
;功能:从C语言中调用汇编语言
AREA Example1,CODE,READONLY ;声明代码段Example1
CODE32 ;声明32位ARM指令
IMPORT __main
EXPORT strcopy
strcopy
LDRB R2,[R1],#1 ;拷贝源字符串的一个字节
STRB R2,[R0],#1 ;将拷贝的字节复制到目标空间,
CMP R2,#0 ;比较R2=0
BNE strcopy
MOV PC,LR
END
复制代码
结果: 将原来的aaaa bbbb的值变成了aaaa aaaa,因此成功实现字符串复制。
test1.4在汇编中调用C函数
;文件名:main.c
;功能:完成求和
int g(int a, int b ,int c,int d)
{
return a+b+c+d;
}
;文件名:TESTFILE.S
;功能:从汇编语言中调用C语言
IMPORT g
AREA Example1,CODE,READONLY
CODE32
ENTRY
START
MOV R0,#1
MOV R1,#2
MOV R2,#3
MOV R3,#10
BL g
MOV R8,R0
B START
END
复制代码
结果: 最终寄存器R8读数为0X000010,正好为1+2+3+10=16,因此正确实现该功能。
test1.5用ARM汇编实现冒泡算法。
AREA Sort,CODE,READONLY
ENTRY
start
MOV r4,#0
LDR r6,=src
ADD r6,r6,#len
outer
LDR r1,=src
inner
LDR r2,[r1]
LDR r3,[r1,#4]
CMP r2,r3
STRGT r3,[r1]
STRGT r2,[r1,#4]
ADD r1,r1,#4
CMP r1,r6
BLT inner
ADD r4,r4,#4
CMP r4,#len
SUBLE r6,r6,#2
BLE outer
src DCD 2,4,10,8,14,1,20
AREA Array,DATA,READWRITE
len EQU 7*4
END
复制代码
结果: 从起始寄存器位置开始,每一个四个输出一个数据,数据依次为1,2,4,8,10,14,20,由此完成了冒泡排序法。
思考:
1.ADD替换成ADDS,SUB替换成SUBS有什么影响?
运算结果不影响CPSR中相应标志位的值,跳转指令由于上一步的CPSR的值没有改
变而没法正确执行。S用于决定指令的操做是否影响CPSR中的条件标志位。
复制代码
2.MOV替换成MOVNE有什么影响?
只有在上一步计算结果为不相等时才执行。MOVNE先判断条件NE (不相等)则转移,能够看做是两条指令NE=NOT EQUAL不相等。
复制代码
3.STMIA换成STMIB,STMIA换成STMDA有什么区别?
STMIA换成STMIB是将每次写入前地址+4改成地址-4,STMIA换成STMDA是将每次写入前地址+4改成+1 ,其中STMIB(地址先增然后完成操做)、STMFA(满递增堆栈);
STMIA(完成操做然后地址递增)、STMEA(空递增堆栈);STMDB(地址先减然后完成操做)、STMFD(满递减堆栈);STMDA(完成操做然后地址递减)、STMED(空递减堆栈)。
复制代码
4.思考用ARM汇编实现1+3+5+…+(2n+1)或者2+4+6+…+2n。
实现1+3+5+„.+(2n+1):
将 add r1,r1,#1 改成 add r1,r1,lsl #1 sub r1,r1,#1
实现2+4+6+…..+2n:
将 add r1,r1,#1 改成 add r1,r1,lsl #1
复制代码
5.实验3中若是去除汇编代码中的“EXPORT strcopy”会有什么现象,为何?
C语言没法调用用strcopy函数。由于EXPORT伪指令用于在程序中声明一个全局的标
号,该标号可在其余的文件中引用。
复制代码
6.实验4中若是去除汇编代码中的“IMPORT …..”会有什么现象,为何?
把“IMPORT ….注释后发现,编译调试时程序单步运行直接从汇编程序开始,说明没法调用C语言的main函数。IMPORT伪操做告诉编译器当前的符号不是在本源文件中定义的,而是在其余源文件中定义的,在本源文件中可能引用该符号,并且不论本源文件是否实际引用该符号,该符号都将被加入到本源文件的符号表中。
复制代码