中
? 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:
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指令从内存文字池读出常量。
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进行初始化;
(2)申请以Str_buffer为起始地址的连续的内存单元,并用字符串“ARM7 and ARM9”进行初始化;
答:(1) data_buffer1 DCW 0x11,0x22,0x33,0x44,0x55 (2) Str_buffer DCB “ARM7 and ARM9”
6.定义一个结构化的内存表,其首地址固定为0x900,该结构化内存表包含2个域,Fdatal长度为8个字节,Fdata2长度为160个字节。 答:MAP 0x900
Fdata1 FIELD 8 Fdata2 FIELD 160
7.在GNU-ARM编译环境下,写出实现下列操作的伪操作:
(1)分配一段字节内存单元,并用57,0x11,031,'Z',0x76进行初始化; (2)分配一段半字内存单元,并用0xFFE0,0xAABB,0x12进行初始化; (3)分配一段字内存单元, 并用0x12345678,0xAABBCCDD进行初始化; (4)分配一段内存单元,并用长为8字节的数值0x11填充100次; 答:
(1)分配一段字节内存单元,并用57,0x11,031,'Z',0x76进行初始化; .byte 57,0x11,031,'Z',0x76
(2)分配一段半字内存单元,并用0xFFE0,0xAABB,0x12进行初始化; .hword 0xFFE0,0xAABB,0x12
(3)分配一段字内存单元, 并用0x12345678,0xAABBCCDD进行初始化; .word 0x12345678,0xAABBCCDD
(4)分配一段内存单元,并用长为8字节的数值0x11填充100次; .fill 100 , 8, 0x11
8.写出与GNU-ARM编译环境下伪操作.arm , .thumb 功能相同的ARM标准开发工具编译环境下的伪操作。
答:.arm 对应 ARM 或 CODE32 .thumb 对应 THUMB 或 CODE16
第7章 汇编语言程序设计
1.分别写出ARM集成开发环境下ARM汇编语句格式与GNU ARM环境下ARM汇编语句通用格式,并分析它们的区别。
答:ADS环境下ARM汇编语句格式如下:
? {symbol} {instruction} {;comment} ? {symbol} {directive} {;comment} ? {symbol} { pseudo-instruction} {;comment}
? Symbol :标号(地址)
? Instruction :指令(ARM/Thumb) ? Directive :伪操作 ? pseudo-instruction:伪指令
GNU环境下ARM汇编语言语句格式如下: