- A64指令集有什么特点?
答:它可以处理64位宽的寄存器和数据并且使用64位的指针来访问内存。
A64指令集有如下特点。
- 具有特有的指令编码格式。
- 只能运行在AArch64状态。
- 指令的宽度为32位。
- A64指令集支持64位宽的数据和地址寻址,为什么指令的编码宽度只有32位?
答:因为A64指令集基于寄存器加载和存储的体系结构设计,所有的数据加载、存储以及处理都是在通用寄存器中完成的。ARM64一共有31个通用寄存器,即X0~X30,因此在指令编码中使用5位宽,这样一共可以索引32(25=32)个通用寄存器。另外,在下面的条件下,我们还可以描述第31个寄存器。
- 当使用寄存器作为基地址时,把SP(栈指针)寄存器当作第31个通用寄存器。
- 当用作源寄存器操作数时,把XZR当作第31个通用寄存器。
- 下面两条指令有什么区别?
LDR X0, [X1]
LDR X0, [X1, #8]
答:第2行代码增加了偏移量。 LDR X0, [X1] // 以X1寄存器中的内容作为内存地址,加载此内存地址的内容到X0寄存器
LDR X0, [X1, #8] // 把X1中的内容加一个偏移量8,以相加的结果作为内存地址,加载此内存地址的内容到X0寄存器
- 在加载和存储指令中,什么是前变基模式与后变基模式?
答:变基模式主要有如下两种。
- 前变基(pre-index)模式:先更新偏移量地址,后访问内存地址。
- 后变基(post-index)模式:先访问内存地址,后更新偏移量地址。
- 在下面的代码中,X0寄存器的值是多少?
my_data:
.word 0x40
ldr x0, my_data
答:X0寄存器的值是0x40。
- 请解释下面的代码。
#define LABEL_1 0x100000
ldr x0, LABEL_1
答:运行上面的代码后,汇编器会报错,因为0x100000的偏移量已经超过这条指令规定的范围了。
- 在下面的代码片段中,X1和X2寄存器的值分别是多少?
my_data:
.quad 0x8a
ldr x5, =my_data
ldrb x1, [x5]
ldrsb x2, [x5]
答:X1寄存器的值为0x8a,X2寄存器的值为0xffffffffffffff8a。
- 在加载与存储指令中,什么是可扩展(scaled)模式和不可扩展(unscaled)模式?
答:可扩展模式和不可扩展模式的区别在于是否按照数据大小来进行扩展,扩大寻址范围。
- 可扩展模式:LDR指令中的基地址加偏移量模式为可扩展模式,即偏移量按照数据大小来扩展并且是正数,取值范围为0~32 760。
- 不可扩展模式:即偏移量只能按照字节来扩展,还可以是正数或负数,取值范围为-256~255,例如LDUR指令。
- 下面几条MOV指令中,哪些能成功执行?哪些会无法正常执行?
mov x0, 0x1234
mov x0, 0x1abcd
mov x0, 0x12bc0000
mov x0, 0xffff0000ffff
答:mov x0, 0x1abcd
会无法正常执行,其他都能成功执行。
- 要加载一个很大的立即数到通用寄存器中,该如何加载?
答:使用LDR伪指令来实现,如下面的代码片段所示。#define BIG_DATA 0xffff_000_ffff_ffff
ldr x0, =BIG_DATA
- 使用如下MOV指令来设置某个寄存器的值,有什么问题?
mov x0, (1 << 0) | (1 << 2) | (1 << 20) | (1 << 40) | (1 << 55)
答:汇编器报如下错误信息。test.S: Assembler messages:
test.S:67: Error: immediate cannot be moved by a single instruction
- 在下面的示例代码中,X0和X1寄存器的值分别是多少?
string1:
.string "Booting at EL"
ldr x0, string1
ldr x1, =string1
答:第一条LDR指令把字符串的ASCII值加载到X0寄存器中。
第二条LDR指令是一条伪指令,它把string1的地址加载到X1寄存器中。
- 在下面的示例代码中,X0和X1寄存器的值分别是多少?
my_data:
.word 0x40
ldr x0, my_data
ldr x1, =my_data
答:第一条LDR指令把my_data存储的数据读出来,即读出0x40。
第二条LDR指令把标签my_data的地址读出来。