16
(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汇编语言语句格式如下:
16
17
? {label :} {instruction} ? {label :} {directive} ? {label :} { pseudo-instruction} {@comment} {@comment} {@comment}
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 R0,#0xB000 ;初始化寄存器 MOV R1,#0x10000001 MOV R2,#100 loop_1 ;第一次循环赋值 STR R1,[R0],#4 ADD R1,R1,#1
17
18
SUBS R2,R2,#1 BNE loop_1 MOV R0,#0xB000 MOV R2,#100 MOV R9,#0 MOV R8,#0 loop_2 ;第二次循环累加 LDR R1,[R0],#4 ADDS R8,R1,R8 ;R8=R8+R1,进位影响标志位 ADDC R9,R9,#0 ;R9=R9+C,C为进位位 SUBS R2,R2,#1 BNE loop_2 Stop B 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 USERMODE 0x10 @用户模式 .equ FIQMODE 0x11 @FIQ模式 .equ IRQMODE 0x12 @IRQ模式 .equ SVCMODE 0x13 @管理模式 .equ ABORTMODE 0x17 @中止模式 .equ UNDEFMODE 0x1B @未定义模式 .equ SYSMODE 0x1F @系统模式 .equ MODEMASK 0x1F @模式位掩码控制字
18
19
.global _start .text .arm _start: MRS R0,CPSR @读取当前CPSR BIC R0,R0,#MODEMASK @清除模式位 @设置系统模式下的SP ORR R1,R0,#SYSMODE MSR CPSR_c,R1 LDR SP,=UserStack @设置中止模式下的SP ORR R1,R0,#ABORTMODE MSR CPSR_c,R1 LDR SP,=AbortStack @设置管理模式下的SP ORR R1,R0,#SVCMODE MSR CPSR_c,R1 LDR SP,=SVCStack @设置IRQ模式下的SP ORR R1,R0,#IRQMODE MSR CPSR_c,R1 LDR SP,=IRQStack @设置FIQ模式下的SP ORR R1,R0,#FIQMODE MSR CPSR_c,R1 LDR SP,=FIQStack
Stop : B Stop .end @文件结束
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
19
20
.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 R0,=Src ;R0=源数据区指针 LDR R1,=Dst ;R1=目标数据区指针 MOV R2,#SRC_NUM ;R2=单字拷贝字数 MOV SP,#0x9000
CMP R2,#6
BLS 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
;将剩余的数据区以字为单位拷贝 Copy_Words ;拷贝剩余字节 LDR R3,[R0],#4 STR R3,[R1],#4 SUBS R2,R2,#1 BNE Copy_Word
20