11
LDRSB指令的二进制编码格式:
LDRB指令用于将内存中的一个8位字节数据读取到指令中的目标寄存器的低8位中,寄存器的高24位用零扩展。
LDRSB指令用于将内存中的一个8位字节数据读取到指令中的目标寄存器的低8位中,寄存器的高24位用符号位扩展。
4.分析下列每条语句的功能,并确定程序段所实现的操作。 CMP R0,,0 MOVEQ R1,,0 MOVGT R1,,1
答:CMP R0,,0 ;比较R0与0的大小
MOVEQ R1,,0 ;若R0==0,则R1=0 MOVGT R1,,1 ;若R0>0,则R1=1
5.请使用多种方法实现将字数据0xFFFFFFFF送入寄存器R0 答:1)MVN R0,#0 2)MOV R0,#1
RSB R0,R0,#0
6.写一条ARM指令,分别完成下列操作: (1)R0=16 (2)R0=R1/16 (3)R1=R2*3 (4)R0=-R0 答:
(1)R0=16 MOV R0,#16 (2)R0=R1/16 MOV R0,R1,LSR #4 (3)R1=R2*3 MOV R3,#3 MUL R1,R2,R3 (4)R0=-R0 RSB R0,R0,#0
7.编写一个ARM汇编程序,累加一个队列中的所有元素,碰到0时停止。结果放入R4。 答:假设队列为地址从R0开始递增的字队列: LOOP
LDR R1, [R0,#4]! MOVS R2, R1 BEQ END
11
12
ADD R4,R4,R2 B LOOP
END
8.写出实现下列操作的ARM指令:
当Z=1时,将存储器地址为R1的字数据读入寄存器R0. 当Z=1时,将存储器地址为R1+R2的字数据读入寄存器R0 将存储器地址为R1-4的字数据读入寄存器R0。
将存储器地址为R1+R6的字数据读入寄存器R0,并将新地址R1+R6写入R1。 答:1)LDREQ R0, [R1] 2)LDREQ R0, [R1,R2] 3)LDR R0, [R1,#-4] 4)LDR R0, [R1,R6]!
9.写出下列ARM指令所实现的操作: LDR R2,[R3,#-4]! LDR R0,[R0],R2 LDR R1,[R3,R2,LSL #2]! LDRSB R0,[R2,#-2]! STRB R1,[R2,,0xA0] LDMIA R0,{R1,R2,R8}
STMDB R0!,{R1-R5,R10,R11} 答:LDR R2,[R3,#-4]! ;R2<-[R3-4], R3=R3-4
LDR R0,[R0],R2 ;R0<-[R0], R0=R0+R2 LDR R1,[R3,R2,LSL #2]! ;R1<-[R3+R2*4], R3=R3+R2*4 LDRSB R0,[R2,#-2]!
;R0低8位<-[R2-2]字节数据,,R0高24位符号扩展,R2=R2-2 STRB R1,[R2,#0xA0] R1低8位->【R2+0xA0】 LDMIA R0,{R1,R2,R8}
从地址R0开始的内存中依次读取字数据,送入寄存器R1,R2,R8 STMDB R0!,{R1-R5,R10,R11}
将寄存器R11,R10,R5-R1的字数据,依次写入地址R0中,每次写入前R0=R0-4
10.SWP指令的优势是什么?
答:SWP指令支持原子操作,它能在一条指令中完成存储器和寄存器之间的数据交换。
11. 如何用带PSR操作的批量字数据加载指令实现IRQ中断的返回?
答:在进入IRQ中断处理程序时,首先计算返回地址,并保存相关的寄存器
? SUB R14,R14,#4 ;
? STMFD R13!, {R0-R3, R12, LR}
如果IRQ中断处理程序返回到被中断的进程则执行下面的指令。该指令从数据栈中恢复寄存器R0~R3及R12的值,将返回地址传送到PC中,并将SPSR_irq值复制到CPSR
12
13
中
? LDMFD R13!, {R0-R3, R12, PC}^
12. 用ARM汇编语言编写代码,实现将ARM处理器切换到用户模式,并关闭中断。 答
:
;禁能IRQ中断 MRS R0 CPSR ORR R0, R0,#0x80
MSR CPSR, R0 ;切换到用户模式 MRS R0 CPSR BIC R0, #0x0F
MSR CPSR, R0
第5章 Thumb指令
1.与32位的ARM指令集相比较,16位的Thumb指令集具有哪些优势?
答:在ARM体系结构中,ARM指令集是32位的,具有很高的执行效率。但是对于嵌入式 而言,其存储空间极其有限,由于每条ARM指令都要占用4个字节,对存储空间的要求较高。为了压缩代码的存储,增加代码存储密度,ARM公司设计了16位的Thumb指令。Thumb代码所需的存储空间约为ARM代码的60%~70%。
2.Thumb指令可分为哪几类?Thumb指令有条件执行指令吗,如果有请说明哪些指令是条件执行的。
答:Thumb指令可分为数据处理指令,存储器操作指令,分支指令,软中断指令。 Thumb指令集只有一条分支指令是有条件的,其余所有指令都是无条件的; B{cond} label
3.分析下面的Thumb指令程序代码,指出程序所完成的功能。 .global _start .text
.equ num 20 _start: MOV SP,#0x400 ADR R0,Thumb_start+1 BX R0 .thumb
Thumb_start: ASR R2,R0,#31 EOR R0,R2 SUB R3,R0,R2 stop:
13
14
B stop .end
答:上述代码首先将处理器状态切换到Thumb状态,
ASR R2,R0,#31 ; 用R0的符号位填充R2 EOR R0,R2 ;如果R0为正数,则R0不变;如果R0为负数,则R0取反 SUB R3,R0,R2 ;R0-R2->R3 (R2为全零或全1)
4.在Thumb状态中,用多种方法实现将寄存器R0中的数据乘以10 答:1)MOV R1,#10 MUL R0,R1
2) LSL R1,R0,#3
LSL R2,R0,#1 ADD R0,R1,R2
5.带链接的分支指令BL提供了一种在Thumb状态下程序间相互调用的方法,当从子程序返回时,可以采用哪种返回方式? 答:通常使用下面的方式之一:
MOV PC, LR BX LR
POP {PC} ;需要在子程序中使用PUSH {LR}
6.指出下列的Thumb程序代码所完成的功能: ASR R0,R1,#31 EOR R1,R0 SUB R1,R0 答:ASR R0,R1,#31 ;用R1的符号位填充R0
EOR R1,R0 ;如果R1为正数,则R1不变;如果R1为负数,则R1取反 SUB R1,R0 ;R1-R0->R1 (R0为全零或全1)
第6章 ARM汇编伪指令与伪操作
1.在ARM汇编语言程序设计中,伪操作与伪指令的区别是什么?
答:伪指令是ARM处理器支持的汇编语言程序里的特殊助记符,它不再处理器运行期间由机器执行,只是在汇编时被合适的机器指令代替成ARM或Thumb指令,从而实现真正的指令操作。
伪操作是ARM汇编语言程序里的一些特殊的指令助记符,其作用主要是为了完成汇编程序做各种准备工作,对源程序运行汇编程序处理,而不是在计算机运行期间由处理器执行。也就是说,这些伪操作只是在汇编过程中起作用,一旦汇编结束,伪操作也就随之消失。
2.分析ARM汇编语言伪指令LDR,ADRL,ADR的汇编结果,说明它们之间的区别。 答: LDR伪指令将一个32位的常数或者一个地址值读取到寄存器中,可以看作是加载寄存器的内容。如果加载的常数符合MOV或MVN指令立即数的要求,则用MOV或MVN指令替代LDR伪指令。如果加载的常数不符合MOV或MVN指令立即数的要求,汇编器将常量放入内存文字池,并使用一条程序相对偏移的LDR指令从内存文字池读出常量。
14
15
ADRL伪指令将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到
寄存器中,比ADR伪指令可以读取更大范围的地址 。在汇编编译器编译源程序时,ADRL伪指令被编译器替换成两条合适的指令。若不能用两条指令实现,则产生错误,编译失败。
ADR伪指令将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄
存器中。在汇编编译器编译源程序时,ADR伪指令被编译器替换成一条合适的指令。通常,编译器用一条ADD指令或SUB指令来实现该ADR伪指令的功能,若不能用一条指令实现,则产生错误,编译失败。
3.在ADS编译环境下,写出下列操作的伪操作:
(1)声明一个局部的算术变量La_var 并将其初始化 0;
(2)声明一个局部的逻辑变量Ll_var 并将其初始化 FALSE; (3)声明一个局部的字符串变量Ls_var 并将其初始化 空串; (4)声明一个全局的逻辑变量Gl_var 并将其初始化 FALSE; (5)声明一个全局的字符串变量Gs_var 并将其初始化 空串; (6)声明一个全局的算术变量Ga_var 并将其初始化 0xAA; (7)声明一个全局的逻辑变量Gl_var 并将其初始化 TRUE;
(8)声明一个全局的字符串变量Gs_var 并将其初始化 “CHINA”; 答:
(1)声明一个局部的算术变量La_var 并将其初始化 0;
LCLA La_var
(2)声明一个局部的逻辑变量Ll_var 并将其初始化 FALSE; LCLL Ll_var
(3)声明一个局部的字符串变量Ls_var 并将其初始化 空串; LCLS Ls_var
(4)声明一个全局的逻辑变量Gl_var 并将其初始化 FALSE; GCLL Gl_var
(5)声明一个全局的字符串变量Gs_var 并将其初始化 空串; GCLS Gs_var
(6)声明一个全局的算术变量Ga_var 并将其初始化 0xAA; GCLA Ga_var
Ga_ var SETA 0xAA
(7)声明一个全局的逻辑变量Gl_var 并将其初始化 TRUE; GCLL Gl_var
Gl_ var SETL TRUE
(8)声明一个全局的字符串变量Gs_var 并将其初始化 “CHINA”; GCLS Gs_var
Gs_ var SETS \
4.用ARM开发工具伪操作将寄存器列表R0-R5,R7,R8的名称定义为Reglist。 答:Reglist RLST {R0-R5,R7,R8}
5.完成下列数据定义伪操作:
(1)申请以data_buffer1为起始地址的连续的内存单元,并依次用半字数据0x11,0x22,0x33,0x44,0x55进行初始化;
15