实验一:
新建工程asm_test3.Uv2, 新建文件asm_test3.s 实现如下功能:先将R1中的低16位传送给R2的高16位,再将R2中的高8位数据传送到R3中的低8位中。
代码:
AREA test2,CODE,READONLY
ENTRY
start
MOV R1, #0xff
MOV R2, R1, LSL #0x10;R1的低16位传送给R2的高16位
MOV R3, R2, LSR #0x14;R2的高8位传送给R3的低8位
NOP
END
心得:
1、立即数范围0-255,6789H表示十六进制常数
2、循环移位:循环左移时移出的位不仅要进CF,而且还要补空出的位
3、检测立即数是否有效的方法:
4、算术左移和逻辑左移在右边空出的位上填0
5、算术右移时,左边空出的位上填符号位(1表示负数,0表示正数),逻辑右移时,左边空出的位上填0。
实验二:
实现求和运算:1+2+3+4+5+…+100
代码:
AREA TEST3,CODE,READONLY
ENTRY
start
MOV R0, #0
MOV R1, #0
MOV R2, #0
loop
ADD R1, R1, #1 ;next value in the register R1:R1_next = R1 + 1
ADD R0, R0, R1 ;R0 += R1
SUBS R2, R1, #100 ;R1 is Variable for controling the cycle
BNE loop
END
心得:
1、关于算术运算如何影响CPSR的条件标志位需要知道CPSR里的条件标志位的含义,如下图:
2、如何根据算术运算的结果来使用条件码,需要知道条件码与CPSR的条件标志位的映射关系,如下图:
3、当有后缀S时,这些指令根据结果更新标志N和Z,在计算Operand2时更新标志C,不影响标志V。
实验三:
新建工程test4.uvproj, 在asm_test4.S文件中依次实现如下功能:
1、使用MOV、ADD指令实现:R8 = R3 = X + Y
2、使用MOV、SUB、LSL指令实现:R5 = 0x5FFFFFF8 - R8 * 8
3、使用CMP指令判断(5*Y/2)>(2*X)吗?若大于则R5 = R5 & 0xFFFF0000,否则R5 = R5|0x000000FF
4、使用TST指令测试R5的bit23是否为1,若是则将bit6位清零(使用BIC指令)
代码(version1):
X EQU 11 ; 定义X的值为11
Y EQU 8 ; 定义Y的值为8
BIT23 EQU (1<<23) ; 定义BIT23的值为0x00800000
AREA test4, CODE, READONLY ;声明代码段test4
ENTRY ;标识程序入口
CODE32 ;申明32位arm指令
start
; 使用MOV、ADD指令实现:R8 = R3 = X + Y
MOV R1, #X ;R1 = X, if X = 1
MOV R2, #Y ;R2 = Y, if Y = 2
ADD R3, R1, R2 ;R3 = X + Y, if R3 = 3
MOV R8, R3 ;R8 = R3, if R8 = 3
; 使用MVN、SUB指令实现:R5 = 0x5FFFFFF8 - R8 * 8
MVN R5, #0xA0000007
SUB R5, R5, R8, LSL #3 ;if R5 = 0x5FFFFFF8 - R8 * 8
; 使用CMP指令判断(5*Y/2)>(2*X)吗?若大于则R5 = R5&0xFFFF0000,否则R5 = R5|0x000000FF
MOV R2, R2, ASR #1 ;if Y / 2
ADD R2, R2, R2, LSL #2 ;if R2 = Y + 4 * Y
MOV R1, R1, LSL #1 ;if R1 = 2*X
CMPHI R2, R1 ;unsigned >
BNE CALLA
ORR R5, R5, #0x000000FF ; R5 = R5|0x000000FF
CALLA
MOV R4, #0xFF000000
ORR R4, R4, #0x00FF0000;R4 = 0xFFFF0000
AND R5, R5, R4 ; R5 = R5 & 0xFFFF0000
; 使用TST指令测试R5的bit23是否为1,若是则将bit6位清零(使用BIC指令)
TST R5, #0x00800000 ;if bit23 = 1
BNE CALLB
CALLB
BIC R5, #0x00000040 ;bit6 = 0
END
代码(version2):
X EQU 11 ; 定义X的值为11
Y EQU 8 ; 定义Y的值为8
BIT23 EQU (1<<23) ; 定义BIT23的值为0x00800000
AREA test2,CODE,READONLY ; 声明代码段test2
ENTRY ; 标识程序入口
CODE32 ; 声明32位ARM指令
START ; 使用MOV、ADD指令实现:R8 = R3 = X + Y
MOV R0,#X ; R0 <= X,X的值必须是有效立即数
MOV R1,#Y ; R1 <= Y,Y的值必须是有效立即数
ADD R3,R0,R1 ; 即是R3 = X + Y
MOV R8,R3 ; R8 <= R3
; 使用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位清零(使用BIC指令)
TST R5,#BIT23
BICNE R5,R5,#0x00000040
B START
END
心得:
1、除2的n次方幂运算都可以 转换位向右移n位的运算
2、乘运算都可以 转换为加运算和向左移n位的复合运算
3、跳转指令通常会和比较指令或算术逻辑运算指令组合使用,而跳转的策略由编程者自己灵活决定,基本原则是根据CPSR里的条件标志位来决策
4、跳转的范围-32MB到32MB
5、指令TST与AND的区别是不保存运算结果,只影响条件标识位,如果它测试的位全都是1时,标志位Z=1,这时条件码EQ将被判断为真,否则标志位Z=0,这时条件码NE将被判断为真
6、指令条件执行方式能减少汇编指令,可以提高程序的执行效率,因为在条件判断为真时,指令才执行,可以实现C语言里的if else结构,比如代码段
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
它实现的一个if else结构,对应的伪代码是
if (5*Y/2)>(2*X)
then
R5 = R5 & 0xFFFF0000
else
R5 = R5|0x000000FF
7、关于常量,十进制,比如1、10;十六进制,比如0xff;n进制,形式n-XXX,比如8进制数8-587;字符常量,‘a’、’\t’;字符串常量,“cdf\t123”; 逻辑常量{TURE},{FALSE}