第 3 章 ARM 指令集( 共 50 分 )
一、 ARM 指令分为几类?分别是什么? ( 6 分)
ARM 指令有五类 (1 分) :分支指令、数据处理指令、存储访问指令、协处理器指令和
杂项指令五类。 (5 类指令各 1 分)
二、 ARM 指令有几种寻址方式?分别是什么? ( 9 分)
ARM 指令有八种寻址方式 (1 分) :立即数寻址、寄存器寻址、寄存器移位寻址、寄存
器间接寻址、基址变址寻址、多寄存器寻址、堆栈寻址、相对寻址。 (8 类寻址各 1 分)
三、单选 ( 35 分,每小题 5 分)
1. 下列指令合法的是( B )
A . MOV R0,#0x132 B . MOV R0,#0x264
C . MOV R0,#0x266 D . MOV R0,#0x4C8
2. 汇编指令 MOV R0,#0x4800, 经编译后,所得到的机器码的低 12 位是( A )
A . 0xB12 B . 0xB24 C . 0xA09 D . 0xC48
3. 假设 R1 寄存器中的值为 ADR ,则在执行了指令: STMIA R1!, {R3-R5,R8} 指令后, R1 的
内容为( A )。
A 、 R1=ADR+16 B 、 R1=ADR+12
C 、 R1=ADR-16 D 、 R1=ADR-12
4. 假设 R1 寄存器中的值为 ADR ,则在执行了指令: STMDB R1!, {R3-R5,R8} 指令后, R5
寄存器中的内容将存放在地址为( B )的存储单元中:
A 、 ADR-4 B 、 ADR-8 C 、 ADR-12 D 、 ADR-16
5. 假设 SP 寄存器中的值为 ADR ,则在执行了指令: STMED SP!, {R3-R5,LR} 指令后, SP 的
内容为( C )。
A 、 ADR+16 B 、 ADR+12 C 、 ADR-16 D 、 ADR-12
6. 假设 SP 寄存器中的值为 ADR ,则在执行了指令: STMED SP!, {R3-R5,LR} 指令后, LR 寄
存器中的内容将存放在地址为( A )的存储单元中。
A 、 ADR B 、 ADR-4 C 、 ADR-12 D 、 ADR-16
7. 假设 SP 寄存器中的值为 ADR ,则在执行了指令: LDMEA SP!, {R3-R5,PC} 指令后,地
址为( B )的存储单元的值,将出栈到 PC 寄存器中。
A 、 ADR B 、 ADR-4 C 、 ADR-12 D 、 ADR-16
第 4 章 ARM 伪指令及编程基础( 共 125 分 )
一、简述指令与伪指令的本质区别是什么? ( 4 分)
指令与伪指令的本质区别是:指令经编译后,会生成对应的机器码 (2 分) 。而伪指令
经编译后没有指令代码。 (2 分)
二、简述伪指令的作用是什么? ( 8 分)
(1)程序定位的作用; (2 分)
(2)为非指令代码进行定义; (2 分)
(3)为程序完整性做标注; (2 分)
(4)有条件的引导程序段。 (2 分)
三、简述宏指令与伪指令的主要区别是什么? ( 4 分)
宏指令与伪指令的主要区别是:在汇编时,这些宏指令被替换成一条或两条真正的 ARM
或 Thumb 指令。而伪指令经编译后没有指令代码。
四、简述伪指令 LTORG 的主要作用和目的。 ( 6 分)
伪指令 LTORG 用来说明某个存储区域为一个用来暂存数据的数据缓冲区,也叫文字池
或数据缓冲池。大的代码段也可以使用多个数据缓冲池。 (3 分)
其目的是,防止在程序中使用 LDR 之类的指令访问时,可能产生的越界。 (3 分)
五、定义一个内存表,其首地址为固定地址 8192 ,该内存表中包含5个数据
域: consta 长度为 4 字节, constb 长度为 4 字节, x 长度为 8 字节, y 长度为 8
字节, string 长度为 16 字节 ( 12 分)
MAP 8192
consta FIELD 4
constb FIELD 4
x FIELD 8
y FIELD 8
string FIELD 16
六、在列表中查找指定的数据 ( 23 分)
要求如下:
(1) 定义一个存储单元首地址名为 Start 的数据列表,该数据列表包含 5 个 字 存储单元。第
一个单元是列表中数据的数量,其值为 4 ,即列表中包含 4 个数据。后面四个单元存储 的是列表中的 4 个数据: 0x0138A, 0x0A21DC, 0x1F5376, 0x9018613 。
(2) 定义一个名为 NewItem 的 字 存储单元,该单元中包含要查找的数据,该例要求是 0x1F5376
(3) 要求编写一个程序,在 Start 数据列表中查找是否包含 NewItem 单元中的数据。如果包
含则把该数据在列表中的位置序号(1、 2 、 3 、 4 )存储到 Index 字 存储单元中。否则在
Index 字 存储单元中存储 0xFFFFFFFF 。
(4) 要求 Start 的数据列表和 NewItem 的 字 存储单元定义在代码段中(只读的 ROM 区),
而 Index 字 存储单元要定义在一个名为 mydata 的数据段中(可读写的 RAM 区)。
程序示例:
AREA mydata,DATA,READWRITE
Index DCD 0xFFFFFFFFAREA pro6,CODE,READONLYENTRYLDR R0,=StartLDR R1,=NewItemLDR R6,=IndexLDR R3,[R1]MOV R4,#1
LOOP LDR R2,[R0, #4]!CMP R2,R3STREQ R4,[R6] ;查找到该数据,将下标存储到IndexADD R4,R4,#1MOVEQ R4,#5 ;查找到该数据,将R4设置为5,退出循环CMP R4,#5 BNE LOOP
Start DCD 4,0x0138A,0x0A21DC,0x1F5376,0x9018613
NewItem DCD 0x1F5376END
七、降序冒泡排序程序 ( 33 分)
(1) 编写一个降序冒泡排序程序,要求如下: ( 22 分)
a) 定义一个存储单元首地址名为 StartOR 的数据列表(在代码段只读 ROM 区),该数
据列表包含若干个 字节存 储单元。第一个单元是列表中数据的数量,后续若干连续
存储单元包含若干字节数据。字节数据的数量由编程人员自己确定。
b) 编程要求把 StartOR 数据列表中存放的数据按降序排序(冒泡排序法)。排序后的
数据存放到名为 Start 的数据列表中,该数据列表定义在名为 mydata 的数据段中
(可读写的 RAM 区)。 Start 数据列表的存储结构与 StartOR 数据列表完全相同。
(2) 要求画出程序流程图。流程图要求黑框白底,分支需要标注转移满足的条件。 (5 分)
大致正确就可以给满分。
(3) 回答问题:为什么 StartOR 数据列表要存放在只读 ROM 区中?而 Start 数据列表需要
存放在 RAM 区中? (6 分)
答:只有存放在 ROM 去的程序和数据,在掉电后才能保持其原值,在上电后 ARM 处
理器才能正确读取存放存放于其中的数据。因此 StartOR 数据列表保存了数据的初始值,需
要在 ROM 中存放。而排序后的结果需要存放于 Start 数据列表中,其对应的存储单元必须
可写,因此 Start 数据列表需要存放在 RAM 区中。( 大致意思正确就可以用给满分 )
AREA mydata,DATA,READWRITE
Start SPACE 6AREA pro7,CODE,READONLYENTRYLDR R0,=StartORLDR R1,=StartLDRB R2,[R0] ;将排序个数送到R2STRB R2,[R1],#1MOV R3,R2 ;R3为比较次数SUB R3,R3,#1
OUTLOOP MOV R4,#0 ;外层循环LDR R0,=StartORADD R0,R0,#1
INNERLOOP ;内层循环LDRB R5,[R0],#1 ;取操作数LDRB R6,[R0] ;取下一个操作数 CMP R5,R6STRBCC R6,[R0,#-1] ;R5操作数小于R6操作数时进行交换STRBCC R5,[R0]ADD R4,R4,#1CMP R4,R3 ;比较R3次BNE INNERLOOPLDRB R7,[R0]STRB R7,[R1,R3]SUBS R3,R3,#1BNE OUTLOOPLDRB R7,[R0,#-1]STRB R7,[R1,R3]
StartOR DCB 5,12,36,3,85,67END
八、编写一个程序段,判断寄存器 R5 中的数据是否为 11 、 15 、 18 、 22 、 44 、
67 ,如果是,则将 R0 中的数据置为 1 ;否则将 R0 设置为 0 ,并把这个程序段
定义为一个代码段,要求先画出程序流程图(流程图要求黑框白底,分支需要
标注转移满足的条件。),再用 ARM 指令写详细代码,程序要完整。 ( 17 分)
AREA pro8,CODE,READONLYENTRYMOV R1,#67TEQ R1,#11TEQNE R1,15TEQNE R1,18TEQNE R1,22TEQNE R1,44TEQNE R1,67MOVEQ R0,#1MOVNE R0,#0END
九、试把如下 C 函数改写成 ARM 指令函数。 ( 9 分)
AREA pro9,CODE,READONLY
EXPORT SUBXX
SUB R0,R0,R1
MOV PC,LR
END
十、把下面的 ARM 指令函数改写成 C 语言函数。 ( 9 分)
void strcopy(char *dest, const char *src) {while (*src != '\0') {*dest = *src;dest++;src++;}*dest = '\0';
}