(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汇编语言语句格式如下:
? {label :} {instruction} {@comment} {@comment} {@comment}
? {label :} {directive} ? {label :} { pseudo-instruction}
2.局部标号提供分支指令在汇编程序的局部范围内跳转,它的主要用途是什么,并举一实例加以说明。 答:局部标号
? 局部标号的语法格式如下:
? n {routname} (0~99) ? 被引用的局部标号语法规则是: ? % {F∣B} {A∣T} n {routname} ? 其中:
? n是局部标号的数字号。(0~99) ? routname是当前局部范围的名称。 ? %表示引用操作。
? F指示汇编器只向前搜索。
? B指示汇编器只向后搜索。
? A指示汇编器搜索宏的所有嵌套层次。 ? T指示汇编器搜索宏的当前层次。
? 局部标号提供分支指令在汇编程序在局部范围内的跳转
3.先对内存地址0xB000开始的100个字内存单元填入0x10000001~0x10000064字数据,然后将每个字单元进行64位累加,结果保存于【R9:R8】(R9中存放高32位)。
答:解:先对内存地址0xB000开始的100个字内存单元填入0x10000001~0x10000064字数据,然后将每个字单元进行64位累加,结果保存于【R9:R8】(R9中存放高32位)。
在ARM集成开发环境下编程:
/*---------------------------------------------------------------------------------------- ********寄存器使用说明************************ ***R0:存放地址值
***R2:递减计数器
***R9:64位递加结果的高32位
***R8:64位递加结果的低32位
*---------------------------------------------------------------------------------------------*/ AREA Fctrl,CODE,READONLY ;声明代码段Fctrl ENTRY ;标识程序入口
CODE32
;声明32位ARM指令
START MOV
MOV
MOV loop_1
STR ADD
R0,#0xB000 R1,#0x10000001 R2,#100 R1,[R0],#4 R1,R1,#1
;初始化寄存器
;第一次循环赋值
SUBS BNE MOV MOV MOV MOV LDR ADDS SUBS BNE B
R2,R2,#1 loop_1 R0,#0xB000 R2,#100 R9,#0 R8,#0 R1,[R0],#4 R8,R1,R8 R2,R2,#1 loop_2 Stop
;文件结束
;第二次循环累加
;R8=R8+R1,进位影响标志位 ;R9=R9+C,C为进位位
loop_2
ADDC R9,R9,#0
Stop
END
4.在GNU环境下用ARM汇编语言编写程序,初始化ARM处理器各模式下的堆栈指针SP_mode (R13),各模式的堆栈指针地址如下:
.equ _ISR_STARTADDRESS, 0xCFFF000 @设置栈的内存基地址 .equ UserStack, _ISR_STARTADDRESS @用户模式堆栈地址 .equ SVCStack, _ISR_STARTADDRESS+64 @管理模式堆栈地址 .equ UndefStack, _ISR_STARTADDRESS+64*2 @未定义模式堆栈地址 .equ AbortStack, _ISR_STARTADDRESS+64*3 @中止模式堆栈地址 .equ IRQStack, _ISR_STARTADDRESS+64*4 @IRQ模式堆栈地址 .equ FIQStack, _ISR_STARTADDRESS+64*5 @FIQ模式堆栈地址 答:
在GNU ARM开发环境下编程:
.equ _ISR_STARTADDRESS, 0xCFFF000 @设置栈的内存基地址 .equ UserStack, _ISR_STARTADDRESS @用户模式堆栈地址 .equ SVCStack, _ISR_STARTADDRESS+64 @管理模式堆栈地址 .equ UndefStack, _ISR_STARTADDRESS+64*2 @未定义模式堆栈地址 .equ AbortStack, _ISR_STARTADDRESS+64*3 @中止模式堆栈地址 .equ IRQStack, _ISR_STARTADDRESS+64*4 @IRQ模式堆栈地址 .equ FIQStack, _ISR_STARTADDRESS+64*5 @FIQ模式堆栈地址
.equ .equ .equ .equ .equ .equ .equ .equ
USERMODE FIQMODE IRQMODE
0x10 0x11 0x12 0x13 0x17 0x1B 0x1F 0x1F
@用户模式 @FIQ模式 @IRQ模式 @管理模式 @中止模式
@未定义模式 @系统模式
@模式位掩码控制字
SVCMODE ABORTMODE UNDEFMODE SYSMODE MODEMASK
.global _start .text .arm _start:
MRS BIC
R0,CPSR
@读取当前CPSR @清除模式位
R0,R0,#MODEMASK
@设置系统模式下的SP ORR R1,R0,#SYSMODE MSR LDR
CPSR_c,R1 SP,=UserStack
@设置中止模式下的SP ORR R1,R0,#ABORTMODE MSR LDR
CPSR_c,R1 SP,=AbortStack
@设置管理模式下的SP ORR MSR LDR
R1,R0,#SVCMODE CPSR_c,R1 SP,=SVCStack
@设置IRQ模式下的SP ORR MSR LDR
R1,R0,#IRQMODE CPSR_c,R1 SP,=IRQStack
@设置FIQ模式下的SP ORR MSR LDR B
R1,R0,#FIQMODE CPSR_c,R1 SP,=FIQStack
Stop : .end
Stop
@文件结束
5.内存数据区定义如下: Src:
.long 1,2,3,4,5,6,7,8,9,0xA,0xB,0xC,0xD,0xE,0xF,0x10 .long 1,2,3,4,5,6,7,8,9,0xA,0xB,0xC,0xD,0xE,0xF,0x10
Src_Num: .long 32 Dst:
.long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
请用ARM指令编写程序,实现将数据从源数据区Src拷贝到目标数据区Dst,要求以6个字为单位进行块拷贝,如果不足6个字时,则以字为单位进行拷贝(其中数据区Src_Num处存放源数据的个数)。
答:解:程序设计思路:每进行6个字的批量拷贝前,先判断SRC_NUM是否大于6,是则进行6字的批量拷贝并将SRC_NUM减去6,否则则进行单字的拷贝,在使用寄存器组时还要注意保存现场。
在ARM集成开发环境下编程:
/*---------------------------------------------------------------------------------------- ********寄存器使用说明************************ ***R0:源数据区指针 ***R1:目标数据区指针 ***R2:单字拷贝字数
***R3:块拷贝字数
***R5~~R10:批量拷贝使用的寄存器组 ***SP:栈指针
*---------------------------------------------------------------------------------------------*/ SRC_NUM EQU 32 ;设置要拷贝的字数
AREA Copy_Data,CODE,READONLY ;声明代码段Copy_Data ENTRY ;标识程序入口 CODE32
;声明32位ARM指令
START LDR LDR
MOV MOV
CMP BLS
R0,=Src R1,=Dst SP,#0x9000
;R0=源数据区指针 ;R1=目标数据区指针 ;R2=单字拷贝字数
R2,#SRC_NUM
R2,#6
Copy_Words
;R2<=6,则拷贝单字
STMFD SP!,{R5-R10} ;保存将要使用的寄存器组R5-R10 ;进行块拷贝,每次拷贝6个字 Copy_6Word LDMIA R0!,{R5-R10}
STMIA R1!,{R5-R10} SUBS R2,R2,#6
BHI Copy_6Word ;R2>6 LDMFD SP!,{R5-R10} ;恢复寄存器组R5-R10 ;将剩余的数据区以字为单位拷贝
;拷贝剩余字节
LDR STR SUBS BNE
R3,[R0],#4 R3,[R1],#4 R2,R2,#1 Copy_Word
Copy_Words