ARM嵌入式系统结构与编程习题答案 清华大学出版社 最详细版 下载本文

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