- 请简述N、Z、C、V这4个条件标志位的作用。
答:如下表所示。
条件标志位 |
描述 |
N |
负数标志(上一次运算结果为负值) |
Z |
零结果标志(上一次运算结果为零) |
C |
进位标志(上一次运算结果发生了无符号数溢出) |
V |
溢出标志(上一次运算结果发生了有符号数溢出) |
- 下面两条ADD指令能否编译成功?
add x0, x1, #4096
add x0, x1, #1, LSL 1
答:不能编译成功。汇编器会报如下错误,其中第一条语句中立即数超过了范围,第二条语句中左移的位数只能是0或者12。 test.S: Assembler messages:
test.S: Error: immediate out of range
test.S: Error: shift amount must be 0 or 12 at operand 3 -- 'add x0,x1,#1,LSL 1'
- 下面的示例代码中,X0寄存器的值是多少?
mov x1, 0xffffffffffffffff
mov x2, #2
adc x0, x1, x2
答:ADC指令的计算过程是0xffffffffffffffff+2+C,因为0xffffffffffffffff+2的过程中已经触发了无符号数溢出,C=1,所以最终计算X0寄存器的值为2。
- 下面的示例代码中,SUBS指令对PSTATE寄存器有什么影响?
mov x1, 0x3
mov x2, 0x1
subs x0. x1. x2
答:会导致C标志位为1。第二个操作数为X2寄存器的值,对应值为1,按位取反之后为0xFFFFFFFFFFFFFFFE。根据计算公式,计算3+0xFFFFFFFFFFFFFFFE+1,这个过程会发生无符号数溢出,因此4个标志位中的C=1,最终计算结果为2。
- 在下面的示例代码中,X0寄存器的值是多少?
mov x1, #3
mov x2, #1
sbc x0, x1, x2
答:X0寄存器的值为2。
- 检查数组array[0, index-1]是否越界,需要判断两个条件:一是输入值是否大于或等于index,二是输入值是否小于0。如下两条指令可实现数组边界检查的功能,其中X0寄存器的值为数组的边界index,X1寄存器的值为输入值input。请解释这两条指令为什么能实现数组越界检查。
subs xzr, x1, x0
b.hs OutOfInex
答:第一条语句是带N、Z、C、V标志位的减法指令。第二条语句中的HS表示是否发生了无符号数溢出,即判断C标志位是否为1。如果C为1,跳转到OutOfIndex标签处,说明发生了溢出。
- 在下面的示例代码中,W2和W3的值是多少?
ldr w1, =0x8000008a
asr w2, w1, 1
lsr w3, w1, 1
答:W2的值是0xC0000045,W3的值是0x40000045。
- 如果想在汇编代码中使某些特定的位翻转,该如何操作?
答:例如,想把0b10100001的第2位和第3位翻转,则可以对该数与0b00000110进行按位异或运算。10100001 ^ 00000110 = 10100111
- 设置某个寄存器A的Bit[7,4]为0x5。下面是C语言的伪代码,用变量val来表示寄存器A的值2,请使用BFI指令来实现。
val &=~ (0xf << 4)
val |= ((u64)0x5 << 4)
答:代码如下。mov x0, #0x2 // 寄存器A的初始值为2
mov x1, #0x5
bfi x0, x1, #4, #4 // 往寄存器A的Bit[7,4]字段设置0x5
BFI指令把X1寄存器中的Bit[3,0]设置为X0寄存器中的Bit[7,4],X0寄存器的值是0x52。
- 下面的示例代码中,X0和X1寄存器的值分别是多少?
mov x2, #0x8a
ubfx x0, x2, #4, #4
sbfx x1, x2, #4, #4
答:X0寄存器的值是0x8,X1寄存器的值是0xFFFFFFFFFFFFFFF8。
- 下面是用C语言来读取pmcr_e10寄存器Bit[15:11]的值,请使用汇编代码来实现。
val = read_sysreg(pmcr_e10)
val = val >> 11;
val &= 0x1f;
答:使用UBFX指令来实现更简洁。mrs x0, pmcr_e10
ubfx x0, x0, #11, #5