【转载】【ARMv8 编程】A64 数据处理指令——移动&比较指令

移动指令主要为 MOV 以及它的各种“变体”,而比较指令主要用来进行比较并更新条件标志,用来实现条件判断等。
指令类型 指令移动 MOV、MVN、MOVK、MOVZ、MOVN比较 CMP、CMN、TST一、移动指令1.1 MOVMOV (to/from SP)在寄存器和堆栈指针之间移动:Rd = Rn。该指令是 ADD(立即数)指令的别名。在这里插入图片描述32-bit (sf == 0)MOV <Wd|WSP>, <Wn|WSP>等价指令ADD <Wd|WSP>, <Wn|WSP>, #064-bit (sf == 1)MOV <Xd|SP>, <Xn|SP>等价指令ADD <Xd|SP>, <Xn|SP>, #0<Wd|WSP> 是目标通用寄存器或堆栈指针的 32 位名称,编码在“Rd”字段中。<Wn|WSP> 是源通用寄存器或堆栈指针的 32 位名称,在“Rn”字段中编码。<Xd|SP> 是目标通用寄存器或堆栈指针的 64 位名称,编码在“Rd”字段中。<Xn|SP> 是源通用寄存器或堆栈指针的 64 位名称,在“Rn”字段中编码。下面是使用 MOV (to/from SP) 指令的例子。 long long int x = 0; asm volatile( “MOV %x[x], SP\n” :[x] “+r”(x) : : “cc”, “memory”);1234567MOV %x[x], SP 指令执行会将 SP 的值移动到 %x[x] 寄存器中,在笔者的机器环境内,某次运行最终 x 的值为 0x7ff7745260。我们先在 asm volatile 代码上加入断点,debug 去看 SP 寄存器的值。在这里插入图片描述此时使用 lldb 命令可以看到 SP 具体值如下:在这里插入图片描述这和我们最终运行得到的 x 值是一致的。MOV (inverted wide immediate)将按位取反的 16 位立即数移动到寄存器:Rd = imm。该指令是 MOVN 指令的别名。在这里插入图片描述32-bit (sf == 0)MOV , #等价指令MOVN , #, LSL #64-bit (sf == 1)MOV , #等价指令MOVN , #, LSL # 是通用目标寄存器的 32 位名称,在“Rd”字段中编码。 是通用目标寄存器的 64 位名称,在“Rd”字段中编码。 对于 32 位变体:是一个 32 位立即数,其按位取反的值可以在“imm16:hw”中编码,但不包括 0xffff0000 和 0x0000ffff; 对于 64 位变体:是一个 64 位立即数,其按位取反的值可以在“imm16:hw”中编码。 是计算出的 16 位立即数,它与 一起编码 NOT()。 对于 32 位变体:是计算的最小左移 0 或 16,应用于 将编码 NOT() 的值;对于 64 位变体:计算的最小左移 0、16、32 或 48 应用于 将编码 NOT() 的值。下面是使用 MOV (inverted wide immediate) 指令的例子。 long long int x = 0; asm volatile( “MOV %x[x], #0xFFFFFFFFFFFFFFF7\n” :[x] “+r”(x) : : “cc”, “memory”);1234567我们将 8(0x0000000000000008) 按位取反就会得到 0xFFFFFFFFFFFFFFF7,接着调用 MOV %x[x], #0xFFFFFFFFFFFFFFF7 指令就会将 0xFFFFFFFFFFFFFFF7 移动到 %x[x] 使用的寄存器,也就是最终 x 的值为 -9(0xFFFFFFFFFFFFFFF7)。MOV (wide immediate)将 16 位立即数移动到寄存器:Rd = imm。该指令是 MOVZ 指令的别名。在这里插入图片描述32-bit (sf == 0)MOV , #等价指令MOVZ , #, LSL #64-bit (sf == 1)MOV , #等价指令MOVZ , #, LSL # 是通用目标寄存器的 32 位名称,在“Rd”字段中编码。 是通用目标寄存器的 64 位名称,在“Rd”字段中编码。 对于 32 位变体:是一个 32 位立即数,可以在“imm16:hw”中编码;对于 64 位变体:是一个 64 位立即数,可以在“imm16:hw”中编码。 是计算出的 16 位立即数,它与 一起编码 。 对于 32 位变体:是计算的最小左移 0 或 16,应用于 将编码 的值;对于 64 位变体:计算的最小左移 0、16、32 或 48 应用于 将编码 的值。下面是使用 MOV (wide immediate) 指令的例子。 long long int x = 0; asm volatile( “MOV %x[x], #8\n” :[x] “+r”(x) : : “cc”, “memory”);1234567执行 MOV %x[x], #8,我们将 8 移动到 %x[x] 使用的寄存器,也就是最终 x 的值为 8。MOV (bitmask immediate)将位掩码立即数移动到寄存器:Rd = imm。该指令是 ORR(立即数)指令的别名。在这里插入图片描述32-bit (sf = 0, N = 0)MOV <Wd|WSP>, #等价指令ORR <Wd|WSP>, WZR, #64-bit (sf == 1)MOV <Xd|SP>, #等价指令ORR <Xd|SP>, XZR, #<Wd|WSP> 是目标通用寄存器或堆栈指针的 32 位名称,在“Rd”字段中编码。<Xd|SP> 是目标通用寄存器或堆栈指针的 64 位名称,在“Rd”字段中编码。 是位掩码立即数,以“N:imms:immr”编码,但不包括可以由 MOVZ 或 MOVN 编码的值。下面是使用 ORR <Xd|SP>, XZR, # 指令的例子,和 MOV <Xd|SP>, # 是等价的,单单从 MOV 立即数指令来看是很难区分出到底是 MOV (inverted wide immediate),还是 MOV (wide immediate),或者是 MOV (bitmask immediate)。 long long int x = 0; asm volatile( “ORR %x[x], XZR, #8\n” :[x] “+r”(x) : : “cc”, “memory”);1234567执行 ORR %x[x], XZR, #8,我们将 8 和 XZR(零值)寄存器进行按位或运算,最后将结果移动到 %x[x] 使用的寄存器,也就是最终 x 的值还为 8。MOV (register)将寄存器的值移动到其他寄存器:Rd = Rm。该指令是 ORR(移位寄存器)指令的别名。在这里插入图片描述32-bit (sf = 0)MOV , 等价指令ORR , WZR, 64-bit (sf == 1)MOV , 等价指令ORR , XZR, 是通用目标寄存器的 32 位名称,在“Rd”字段中编码。 是通用源寄存器的 32 位名称,在“Rm”字段中编码。 是通用目标寄存器的 64 位名称,在“Rd”字段中编码。 是通用源寄存器的 64 位名称,在“Rm”字段中编码。下面是使用 MOV (register) 指令的例子。 long long int x = 0; long long int y = 8; asm volatile( “MOV %x[x], %x[y]\n” :[x] “+r”(x), [y] “+r”(y) : : “cc”, “memory”);123456789执行 MOV %x[x], %x[y],我们将 %x[y](即 8) 移动到 %x[x] 使用的寄存器,也就是最终 x 的值为 8。1.2 MOVKMove wide with keep 将一个可选移位的 16 位立即值移动到一个寄存器中,保持其他位不变。在这里插入图片描述32-bit (sf == 0 && hw == 0x)MOVK , #{, LSL #}64-bit (sf == 1)MOVK , #{, LSL #} 是通用目标寄存器的 32 位名称,在“Rd”字段中编码。 是通用目标寄存器的 64 位名称,在“Rd”字段中编码。 是 16 位无符号立即数,范围为 0 到 65535,在“imm16”字段中编码。 对于 32 位变体:是立即向左移动的量,0(默认值)或 16,在“hw”字段中编码为 /16;对于 64 位变体:是向左移动的量,可以是 0(默认值)、16、32 或 48,在“hw”字段中编码为 /16。下面是使用 MOVK 指令的例子。 long long int x = 0; long long int y = -1; asm volatile( “MOV %x[x], %x[y]\n” “MOVK %x[x], #0xf5b7, LSL#16\n” :[x] “+r”(x), [y] “+r”(y) : : “cc”, “memory”);12345678910执行 MOV %x[x], %x[y],我们将 %x[y](0xFFFF FFFF FFFF FFFF(-1 的 64 位补码形式)) 的值移动到 %x[x],接着执行 MOVK %x[x], #0xf5b7, LSL#16,先将 0xf5b7 逻辑左移 16 位,然后移动到 %x[x] 寄存器,由于要保持 %x[x] 寄存器内其他位不变,因此其内部值变为 0xFFFF FFFF F5B7 FFFF,注意 f5b7 的位置,它是直接替换 %x[x] 寄存器对应的位!这也是最终 x 的值。1.3 MOVNMOVN(Move wide with NOT)指令将可选移位的 16 位立即数的按位取反值移动到寄存器。该指令由别名 MOV(inverted wide immediate)使用。在这里插入图片描述32-bit (sf == 0 && hw == 0x)MOVN , #{, LSL #}64-bit (sf == 1)MOVN , #{, LSL #} 是通用目标寄存器的 32 位名称,在“Rd”字段中编码。 是通用目标寄存器的 64 位名称,在“Rd”字段中编码。 是 16 位无符号立即数,范围为 0 到 65535,在“imm16”字段中编码。 对于 32 位变体:是立即向左移动的量,0(默认值)或 16,在“hw”字段中编码为 /16;对于 64 位变体:是向左移动的量,可以是 0(默认值)、16、32 或 48,在“hw”字段中编码为 /16。下面是使用 MOVN 指令的例子。 long long int x = 0xff; asm volatile( “MOVN %x[x], #0x80ff, LSL#16\n” :[x] “+r”(x) : : “cc”, “memory”);1234567执行 MOVN %x[x], #0x80ff, LSL#16,将 0x80ff 逻辑左移 16 位,即得到 0x80FF0000,然后按位取反 0xFFFF FFFF 7F00 FFFF,把这个值移动到寄存器 %x[x],这也是最终 x 的值。不难看出这里的值完全覆盖了 %x[x] 寄存器的初始值 0xFF。1.4 MOVZMOVZ(Move wide with zero)指令将一个可选移位的 16 位立即值移动到一个寄存器。 该指令由别名 MOV(wide immediate)使用。在这里插入图片描述32-bit (sf == 0 && hw == 0x)MOVZ , #{, LSL #}64-bit (sf == 1)MOVZ , #{, LSL #} 是通用目标寄存器的 32 位名称,在“Rd”字段中编码。 是通用目标寄存器的 64 位名称,在“Rd”字段中编码。 是 16 位无符号立即数,范围为 0 到 65535,在“imm16”字段中编码。 对于 32 位变体:是立即向左移动的量,0(默认值)或 16,在“hw”字段中编码为 /16;对于 64 位变体:是向左移动的量,可以是 0(默认值)、16、32 或 48,在“hw”字段中编码为 /16。下面是使用 MOVZ 指令的例子。 long long int x = 0xff; asm volatile( “MOVZ %x[x], #0x80ff, LSL#16\n” :[x] “+r”(x) : : “cc”, “memory”);1234567执行 MOVZ %x[x], #0x80ff, LSL#16,将 0x80ff 逻辑左移 16 位,即得到 0x80FF0000,把这个值移动到寄存器 %x[x],这也是最终 x 的值。不难看出这里的值完全覆盖了 %x[x] 寄存器的初始值 0xFF。1.5 MVNMVN(按位非)指令将寄存器值的按位取反写入目标寄存器。 该指令是 ORN(移位寄存器)指令的别名。在这里插入图片描述32-bit (sf == 0)MVN , {, #}等价指令ORN , WZR, {, #}64-bit (sf == 1)MVN , {, #}等价指令ORN , XZR, {, #} 是通用目标寄存器的 32 位名称,在“Rd”字段中编码。 是通用源寄存器的 32 位名称,在“Rm”字段中编码。 是通用目标寄存器的 64 位名称,在“Rd”字段中编码。 是通用源寄存器的 64 位名称,在“Rm”字段中编码。 是应用于最终源的可选移位,默认为 LSL 并在“shift”字段中编码。 它可以具有以下值: shift 字段取值LSL shift = 00LSR shift = 01ASR shift = 10ROR shift = 11 对于 32 位变体:是移位量,范围为 0 到 31,默认为 0 并在“imm6”字段中编码。对于 64 位变体:是移位量,在 0 到 63 范围内,默认为 0 并在“imm6”字段中编码。下面是使用 MVN 指令的例子。 long long int x = 0xff; long long int y = 0x80; asm volatile( “MVN %x[x], %x[y], LSL#16\n” :[x] “+r”(x), [y] “+r”(y) : : “cc”, “memory”);123456789执行 MVN %x[x], %x[y], LSL#16,将 %x[y] 寄存器的值逻辑左移 16 位,也就是 0x80 逻辑左移 16 位,即得到 0x800000,接着将其取反 0xFFFF FFFF FF7F FFFF,把这个值移动到寄存器 %x[x],这也是最终 x 的值。二、比较指令A64 指令集不支持对每条指令进行条件执行。指令的预测执行并不能提供足够的好处来证明其对操作码空间的大量使用是合理的。条件标志见下表:标志 名称 详细描述N 负(Negative) 设置为与结果的位 [31] 相同的值。对于 32 位有符号整数,设置位 [31] 表示该值为负数。Z 零(Zero) 如果结果为零则设置为 1,否则设置为 0。C 进位(Carry) 设置为结果的进位值,或设置为从移位操作移出的最后一位的值。V 溢出(Overflow) 如果发生有符号溢出或下溢,则设置为 1,否则设置为 0。如果无符号运算的结果溢出结果寄存器,则设置 C 标志。V 标志的操作方式与 C 标志相同,但用于带符号的操作。CMP 和 CMN 如果原始条件为真,则将条件标志设置为比较结果。如果不为真,则将条件标志设置为指定的条件标志状态。条件比较指令对于表达嵌套或复合比较非常有用。条件码表如下:Code 编码 含义(当由 CMP 设置时) 含义(当由 FCMP 设置时) 条件标志EQ 0b0000 等于 等于 Z = 1NE 0b0001 不等于 无序或不等于 Z = 0CS 0b0010 进位设置(与 HS 相同) 大于、等于或无序(与 HS 相同) C = 1HS 0b0010 大于,等于(无符号)(与 CS 相同) 大于、等于或无序(与 CS 相同) C = 1CC 0b0011 进位清除(与 LO 相同) 小于(与 LO 相同) C = 0LO 0b0011 无符号小于(与 CC 相同) 小于(与 CC 相同) C = 0MI 0b0100 Minus,Negative(负的) 小于 N = 1PL 0b0101 正数或零 大于、等于或无序 N = 0VS 0b0110 有符号溢出 无序。(至少有一个参数是 NaN) V = 1VC 0b0111 无符号溢出 不是无序的。(没有参数是 NaN) V = 0HI 0b1000 大于(无符号) 大于或无序 (C = 1) && (Z = 0)LS 0b1001 小于或等于(无符号) 小于或等于 (C = 0) || (Z = 1)GE 0b1010 大于或等于(有符号) 大于或等于 N == VLT 0b1011 小于(有符号) 小于或无序 N != VGT 0b1100 大于(有符号) 大于 (Z == 0) && (N == V)LE 0b1101 小于或等于(有符号) 小于、等于或无序 (Z == 1) || (N != V)AL 0b1110 总是执行 默认。总是执行 AnyNV 0b1111 总是执行 总是执行 Any2.1 CMPCMP (extended register)比较(扩展寄存器)指令从寄存器值中减去符号或零扩展寄存器值(后跟可选的左移量)。 从 寄存器扩展的参数可以是字节、半字、字或双字。 它根据结果更新条件标志,并丢弃结果。 该指令是 SUBS(扩展寄存器)指令的别名。在这里插入图片描述32-bit (sf == 0)CMP <Wn|WSP>, {, {#}}等价指令SUBS WZR, <Wn|WSP>, {, {#}}64-bit (sf == 1)CMP <Xn|SP>, {, {#}}等价指令SUBS XZR, <Xn|SP>, {, {#}}<Wn|WSP> 是第一个源通用寄存器或堆栈指针的 32 位名称,在“Rn”字段中编码。 是第二个通用源寄存器的 32 位名称,在“Rm”字段中编码。<Xn|SP> 是第一个源通用寄存器或堆栈指针的 64 位名称,在“Rn”字段中编码。 是宽度说明符,在“option”字段中编码。 它可以具有以下值:R optionW 00xW 010X x11W 10xW 110 是第二个通用源寄存器的编号 [0-30] 或名称 ZR (31),编码在“Rm”字段中。 对于 32 位变体:是应用于第二个源操作数的扩展,编码在“option”字段中。 它可以具有以下值:extend optionUXTB 000UXTH 001LSL|UXTW 010UXTX 011SXTB 100SXTH 101SXTW 110SXTX 111如果“Rn”为“11111”(WSP)且“option”为“010”,则首选 LSL,但当“imm3”为“000”时可以省略。在所有其他情况下, 是必需的,并且当“option”为“010”时必须为 UXTW。 对于 64 位变体:是应用于第二个源操作数的扩展,在“选项”字段中编码。 它可以具有以下值:extend optionUXTB 000UXTH 001UXTW 010LSL|UXTX 011SXTB 100SXTH 101SXTW 110SXTX 111如果“Rn”为“11111”(SP)且“option”为“011”,则首选 LSL,但当“imm3”为“000”时可省略。在所有其他情况下, 是必需的,并且当“option”为“011”时必须是 UXTX。 是扩展后要应用的左移量,范围为 0 到 4,默认为 0,编码在“imm3”字段中。 当 不存在时它必须不存在,当 是 LSL 时它是必需的,并且当 存在但不是 LSL 时它是可选的。下面是使用 CMP (extended register) 指令的例子。 long

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值