04-A64指令集2——算术与移位指令

本章思考题

  1. 请简述N、Z、C、V这4个条件标志位的作用。
    答:如下表所示。
    条件标志位 描述
    N 负数标志(上一次运算结果为负值)
    Z 零结果标志(上一次运算结果为零)
    C 进位标志(上一次运算结果发生了无符号数溢出)
    V 溢出标志(上一次运算结果发生了有符号数溢出)
  2. 下面两条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'
    
  3. 下面的示例代码中,X0寄存器的值是多少?
     mov x1, 0xffffffffffffffff
     mov x2, #2
     adc x0, x1, x2
    
    答:ADC指令的计算过程是0xffffffffffffffff+2+C,因为0xffffffffffffffff+2的过程中已经触发了无符号数溢出,C=1,所以最终计算X0寄存器的值为2。
  4. 下面的示例代码中,SUBS指令对PSTATE寄存器有什么影响?
     mov x1, 0x3
     mov x2, 0x1
     subs x0. x1. x2
    
    答:会导致C标志位为1。第二个操作数为X2寄存器的值,对应值为1,按位取反之后为0xFFFFFFFFFFFFFFFE。根据计算公式,计算3+0xFFFFFFFFFFFFFFFE+1,这个过程会发生无符号数溢出,因此4个标志位中的C=1,最终计算结果为2。
  5. 在下面的示例代码中,X0寄存器的值是多少?
     mov x1, #3
     mov x2, #1
     sbc x0, x1, x2
    
    答:X0寄存器的值为2。
  6. 检查数组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标签处,说明发生了溢出。
  7. 在下面的示例代码中,W2和W3的值是多少?
    ldr w1, =0x8000008a
    asr w2, w1, 1
    lsr w3, w1, 1 
    
    答:W2的值是0xC0000045,W3的值是0x40000045。
  8. 如果想在汇编代码中使某些特定的位翻转,该如何操作?
    答:例如,想把0b10100001的第2位和第3位翻转,则可以对该数与0b00000110进行按位异或运算。
    10100001 ^ 00000110 = 10100111
    
  9. 设置某个寄存器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。
  10. 下面的示例代码中,X0和X1寄存器的值分别是多少?
    mov x2, #0x8a
    ubfx x0, x2, #4, #4
    sbfx x1, x2, #4, #4
    
    答:X0寄存器的值是0x8,X1寄存器的值是0xFFFFFFFFFFFFFFF8。
  11. 下面是用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
    
posted @ 2024-04-06 21:13  Hellofds  阅读(35)  评论(0编辑  收藏  举报