【ARMv8 编程】A64 数据处理指令——逻辑移位指令
逻辑指令包括与、或等指令,移位指令则分为逻辑移位和算术移位指令,下面则详细展开学习。
指令类型 | 指令 |
---|---|
逻辑 | AND、BIC、ORR、ORN、EOR、EON |
移位 | ASR、LSL、LSR、ROR |
逻辑运算本质上与对寄存器的各个位进行运算的相应布尔运算符相同。
• 逻辑左移(LSL)。 LSL 指令执行乘以 2 的幂。
• 逻辑右移(LSR)。 LSR 指令执行除以 2 的幂。
• 算术右移(ASR)。 ASR 指令执行除以 2 的幂,保留符号位。
• 循环右移(ROR)。 ROR 指令执行按位循环,将循环后的位从 LSB 移动到 MSB。
一、逻辑指令
1.1 AND
AND(立即数)
按位与(立即数)指令执行寄存器值和立即数的按位与,并将结果写入目标寄存器。
32-bit (sf == 0 && N == 0)
AND <Wd|WSP>, <Wn>, #<imm>
64-bit (sf == 1)
AND <Xd|SP>, <Xn>, #<imm>
<Wd|WSP>
是目标通用寄存器或堆栈指针的 32 位名称,编码在“Rd”字段中。
<Wn>
是通用源寄存器的 32 位名称,在“Rn”字段中编码。
<Xd|SP>
是目标通用寄存器或堆栈指针的 64 位名称,在“Rd”字段中编码。
<Xn>
是通用源寄存器的 64 位名称,在“Rn”字段中编码。
<imm>
对于 32 位变体:是位掩码立即数,编码为“imms:immr”;对于 64 位变体:是位掩码立即数,编码为“N:imms:immr”。
下面是使用 AND(立即数)指令的例子。
long long int y = -1;long long int z = 100;asm volatile("AND %x[z], %x[y], #4\n":[y] "+r"(y),[z] "+r"(z):: "cc", "memory");
AND %x[z], %x[y], #4
将 z & y 并只取后 4 位(掩码),也就是 0xFFFF FFFF FFFF FFFF & 0x64 = 0x64(0b0110 0100),取后四位即 0b0100,也就是 4,所以 z 的值最终为 4。这里需要说明的一点是 -1 需要补码表示,存储在计算机内就是 64 位全为 1。
AND(移位寄存器)
按位与(移位寄存器)指令执行寄存器值和可选移位寄存器值的按位与,并将结果写入目标寄存器。
32-bit (sf == 0)
AND <Wd>, <Wn>, <Wm>{, <shift> #<amount>}
64-bit (sf == 1)
AND <Xd>, <Xn>, <Xm>{, <shift> #<amount>}
<Wd>
是通用目标寄存器的 32 位名称,在“Rd”字段中编码。
<Wn>
是第一个通用源寄存器的 32 位名称,在“Rn”字段中编码。
<Wm>
是第二个通用源寄存器的 32 位名称,在“Rm”字段中编码。
<Xd>
是通用目标寄存器的 64 位名称,在“Rd”字段中编码。
<Xn>
是第一个通用源寄存器的 64 位名称,在“Rn”字段中编码。
<Xm>
是第二个通用源寄存器的 64 位名称,在“Rm”字段中编码。
<shift>
是应用于最终源的可选移位,默认为 LSL 并在“shift”字段中编码。 它可以具有以下值:
<shift> | shift 字段取值 |
---|---|
LSL | shift = 00 |
LSR | shift = 01 |
ASR | shift = 10 |
ROR | shift = 11 |
<amount>
对于 32 位变体:是移位量,范围为 0 到 31,默认为 0 并在“imm6”字段中编码;对于 64 位变体:是移位量,在 0 到 63 范围内,默认为 0 并在“imm6”字段中编码。
下面是使用 AND(移位寄存器)指令的例子。
long long int x = -1;long long int y = 4;long long int z = 0;asm volatile("AND %x[z], %x[x], %x[y], LSL#4\n":[x] "+r"(x),[y] "+r"(y),[z] "+r"(z):: "cc", "memory");
AND %x[z], %x[x], %x[y], LSL#4
将 x & (y << 4) ,也就是 0xFFFF FFFF FFFF FFFF & (4 * (2^4)) = 64,所以 z 的值最终为 64。
1.2 BIC
按位清零(移位寄存器):Rd = Rn AND NOT shift(Rm, amount)。
32-bit (sf = 0)
BIC <Wd>, <Wn>, <Wm>{, <shift> #<amount>}
64-bit (sf = 1)
BIC <Xd>, <Xn>, <Xm>{, <shift> #<amount>}
<Wd>
是通用目标寄存器的 32 位名称,在“Rd”字段中编码。
<Wn>
是第一个通用源寄存器的 32 位名称,在“Rn”字段中编码。
<Wm>
是第二个通用源寄存器的 32 位名称,在“Rm”字段中编码。
<Xd>
是通用目标寄存器的 64 位名称,在“Rd”字段中编码。
<Xn>
是第一个通用源寄存器的 64 位名称,在“Rn”字段中编码。
<Xm>
是第二个通用源寄存器的 64 位名称,在“Rm”字段中编码。
<shift>
是要应用于最终源的可选移位,默认为 LSL 并在移位字段中编码:
<shift> | shift 字段取值 |
---|---|
LSL | shift = 00 |
LSR | shift = 01 |
ASR | shift = 10 |
ROR | shift = 11 |
<amount>
对于 32 位变体:是移位量,范围为 0 到 31,默认为 0 并在“imm6”字段中编码;对于 64 位变体:是移位量,在 0 到 63 范围内,默认为 0 并在“imm6”字段中编码。
下面是使用 BIC 指令的例子。
long long int x = 0b01101100;//108long long int y = 0b00110000;//48long long int z = 0;asm volatile("BIC %x[z], %x[x], %x[y], LSL#1\n":[x] "+r"(x),[y] "+r"(y),[z] "+r"(z):: "cc", "memory");
BIC %x[z], %x[x], %x[y], LSL#1
执行 x & (~(y << 1)) = 0b01101100 & (~0b01100000) = 0b01101100 & 0b1…110011111 = 0b1100,也就是 12,所以 z 的最终结果为 12(0b1100)。0b1…110011111(共 64 位 1…1 之间省略了其他 1)。
BICS
唯一不同的一点是会设置条件标志。
1.3 ORR
ORR(立即数)
按位或(立即数):Rd = Rn OR imm。
32-bit (sf = 0, N = 0)
ORR <Wd|WSP>, <Wn>, #<imm>
64-bit (sf = 1)
ORR <Xd|SP>, <Xn>, #<imm>
<Wd|WSP>
是目标通用寄存器或堆栈指针的 32 位名称,在“Rd”字段中编码。
<Wn>
是通用源寄存器的 32 位名称,在“Rn 字段中编码。
<Xd|SP>
是目标通用寄存器或堆栈指针的 64 位名称,在“Rd”字段中编码。
<Xn>
是通用源寄存器的 64 位名称,在“Rn”字段中编码。
<imm>
是位掩码立即数,编码为 N:imms:immr。
下面是使用 ORR(立即数)指令的例子。
long long int x = 0b01101100;//108long long int z = 0;asm volatile("ORR %x[z], %x[x], #0b1111\n":[x] "+r"(x),[z] "+r"(z):: "cc", "memory");
ORR %x[z], %x[x], L#0b1111
执行 x | 0b1111 = 0b01101100 | 0b1111 = 0b01101111,也就是 111,所以 z 的最终结果为 111。
ORR(移位寄存器)
按位或(移位寄存器):Rd = Rn OR shift(Rm, amount)。
32-bit (sf = 0)
ORR <Wd>, <Wn>, <Wm>{, <shift> #<amount>}
64-bit (sf = 1)
ORR <Xd>, <Xn>, <Xm>{, <shift> #<amount>}
<Wd>
是通用目标寄存器的 32 位名称,在“Rd”字段中编码。
<Wn>
是第一个通用源寄存器的 32 位名称,在“Rn”字段中编码。
<Wm>
是第二个通用源寄存器的 32 位名称,在“Rm”字段中编码。
<Xd>
是通用目标寄存器的 64 位名称,在“Rd”字段中编码。
<Xn>
是第一个通用源寄存器的 64 位名称,在“Rn”字段中编码。
<Xm>
是第二个通用源寄存器的 64 位名称,在“Rm”字段中编码。
<shift>
是要应用于最终源的可选移位,默认为 LSL 并在移位字段中编码:
<shift> | shift 字段取值 |
---|---|
LSL | shift = 00 |
LSR | shift = 01 |
ASR | shift = 10 |
ROR | shift = 11 |
<amount>
对于 32 位变体:是移位量,范围为 0 到 31,默认为 0 并在“imm6”字段中编码;对于 64 位变体:是移位量,在 0 到 63 范围内,默认为 0 并在“imm6”字段中编码。
下面是使用 ORR(移位寄存器)指令的例子。
long long int x = 0b01101100;//108long long int y = 0b00110000;//48long long int z = 0;asm volatile("ORR %x[z], %x[x], %x[y], LSL#2\n":[x] "+r"(x),[y] "+r"(y),[z] "+r"(z):: "cc", "memory");
ORR %x[z], %x[x], %x[y], LSL#2
执行 x | (y << 2) = 0b01101100 | 0b11000000 = 0b11101100,也就是 236,所以 z 的最终结果为 236。
1.4 ORN
按位或非(移位寄存器):Rd = Rn OR NOT shift(Rm, amount)。
32-bit (sf = 0)
ORN <Wd>, <Wn>, <Wm>{, <shift> #<amount>}
64-bit (sf = 1)
ORN <Xd>, <Xn>, <Xm>{, <shift> #<amount>}
<Wd>
是通用目标寄存器的 32 位名称,在“Rd”字段中编码。
<Wn>
是第一个通用源寄存器的 32 位名称,在“Rn”字段中编码。
<Wm>
是第二个通用源寄存器的 32 位名称,在“Rm”字段中编码。
<Xd>
是通用目标寄存器的 64 位名称,在“Rd”字段中编码。
<Xn>
是第一个通用源寄存器的 64 位名称,在“Rn”字段中编码。
<Xm>
是第二个通用源寄存器的 64 位名称,在“Rm”字段中编码。
<shift>
是要应用于最终源的可选移位,默认为 LSL 并在移位字段中编码:
<shift> | shift 字段取值 |
---|---|
LSL | shift = 00 |
LSR | shift = 01 |
ASR | shift = 10 |
ROR | shift = 11 |
<amount>
对于 32 位变体:是移位量,范围为 0 到 31,默认为 0 并在“imm6”字段中编码;对于 64 位变体:是移位量,在 0 到 63 范围内,默认为 0 并在“imm6”字段中编码。
下面是使用 ORN 指令的例子。
long long int x = 0b01101100;//108long long int y = 0b00110000;//48long long int z = 0;asm volatile("ORN %x[z], %x[x], %x[y], LSL#2\n":[x] "+r"(x),[y] "+r"(y),[z] "+r"(z):: "cc", "memory");
ORN %x[z], %x[x], %x[y], LSL#2
执行 x | (~(y << 2)) = 0b01101100 | (~(0b11000000)) = 0b01101100 | 0xFFFF FFFF FFFF FF3F = 0xFFFF FFFF FFFF FF7F,也就是 -129,所以 z 的最终结果为 -129。这里需要注意的一点是取反操作是将寄存器内的 64 位都做取反操作的!
1.5 EOR
EOR(立即数)
按位异或(立即数):Rd = Rn EOR imm。
32-bit (sf = 0)
EOR <Wd|WSP>, <Wn>, #<imm>
64-bit (sf = 1)
EOR <Xd|SP>, <Xn>, #<imm>
<Wd|WSP>
是目标通用寄存器或堆栈指针的 32 位名称,在“Rd”字段中编码。
<Wn>
是通用源寄存器的 32 位名称,在“Rn”字段中编码。
<Xd|SP>
是目标通用寄存器或堆栈指针的 64 位名称,在“Rd”字段中编码。
<Xn>
是通用源寄存器的 64 位名称,在“Rn”字段中编码。
<imm>
是位掩码立即数,编码为 N:imms:immr。
下面是使用 EOR(立即数)指令的例子。
long long int x = 0b01101100;//108long long int z = 0;asm volatile("EOR %x[z], %x[x], #0b01100000\n":[x] "+r"(x),[z] "+r"(z):: "cc", "memory");
EOR %x[z], %x[x], #0b01100000
执行 x 异或 0b01100000 = 0b01101100 异或 0b01100000 = 0b1100,也就是 12,所以 z 的最终结果为 12。
EOR(移位寄存器)
按位异或(移位寄存器):Rd = Rn EOR shift(Rm, amount)。
32-bit (sf = 0)
EOR <Wd>, <Wn>, <Wm>{, <shift> #<amount>}
64-bit (sf = 1)
EOR <Xd>, <Xn>, <Xm>{, <shift> #<amount>}
<Wd>
是通用目标寄存器的 32 位名称,在“Rd”字段中编码。
<Wn>
是第一个通用源寄存器的 32 位名称,在“Rn”字段中编码。
<Wm>
是第二个通用源寄存器的 32 位名称,在“Rm”字段中编码。
<Xd>
是通用目标寄存器的 64 位名称,在“Rd”字段中编码。
<Xn>
是第一个通用源寄存器的 64 位名称,在“Rn”字段中编码。
<Xm>
是第二个通用源寄存器的 64 位名称,在“Rm”字段中编码。
<shift>
是要应用于最终源的可选移位,默认为 LSL 并在移位字段中编码:
<shift> | shift 字段取值 |
---|---|
LSL | shift = 00 |
LSR | shift = 01 |
ASR | shift = 10 |
ROR | shift = 11 |
<amount>
对于 32 位变体:是移位量,范围为 0 到 31,默认为 0 并在“imm6”字段中编码;对于 64 位变体:是移位量,在 0 到 63 范围内,默认为 0 并在“imm6”字段中编码。
下面是使用 EOR(移位寄存器)指令的例子。
long long int x = 0b01101100;//108long long int y = 0b00110000;//48long long int z = 0;asm volatile("EOR %x[z], %x[x], %x[y], LSL#2\n":[x] "+r"(x),[y] "+r"(y),[z] "+r"(z):: "cc", "memory");
EOR %x[z], %x[x], %x[y], LSL#2
执行 x 异或 (y << 2) = 0b01101100 异或 0b11000000 = 0b10101100,也就是 172,所以 z 的最终结果为 172。
1.6 EON
按位异或非(移位寄存器):Rd = Rn EOR NOT shift(Rm, amount)。
32-bit (sf = 0)
EON <Wd>, <Wn>, <Wm>{, <shift> #<amount>}
64-bit (sf = 1)
EON <Xd>, <Xn>, <Xm>{, <shift> #<amount>}
<Wd>
是通用目标寄存器的 32 位名称,在“Rd”字段中编码。
<Wn>
是第一个通用源寄存器的 32 位名称,在“Rn”字段中编码。
<Wm>
是第二个通用源寄存器的 32 位名称,在“Rm”字段中编码。
<Xd>
是通用目标寄存器的 64 位名称,在“Rd”字段中编码。
<Xn>
是第一个通用源寄存器的 64 位名称,在“Rn”字段中编码。
<Xm>
是第二个通用源寄存器的 64 位名称,在“Rm”字段中编码。
<shift>
是要应用于最终源的可选移位,默认为 LSL 并在移位字段中编码:
<shift> | shift 字段取值 |
---|---|
LSL | shift = 00 |
LSR | shift = 01 |
ASR | shift = 10 |
ROR | shift = 11 |
<amount>
对于 32 位变体:是移位量,范围为 0 到 31,默认为 0 并在“imm6”字段中编码;对于 64 位变体:是移位量,在 0 到 63 范围内,默认为 0 并在“imm6”字段中编码。
下面是使用 EON 指令的例子。
long long int x = 0b01101100;//108long long int y = 0b00110000;//48long long int z = 0;asm volatile("EON %x[z], %x[x], %x[y], LSL#2\n":[x] "+r"(x),[y] "+r"(y),[z] "+r"(z):: "cc", "memory");
EON %x[z], %x[x], %x[y], LSL#2
执行 x 异或 ~(y << 2) = 0b01101100 异或 ~0b11000000 = 0b01101100 异或 0xFFFF FFFF FFFF FF3F = 0xFFFF FFFF FFFF FF53,也就是 -173,所以 z 的最终结果为 -173。
二、移位指令
指定用于移位的寄存器可以是 32 位或 64 位。要移位的量可以指定为立即数,即最大寄存器大小减一,或者指定值仅取自底部五位(模 32)或六位(模 64)位的寄存器。
下面的图详细解释了移位指令是如何操作的。
2.1 ASR
ASR(寄存器)
算术右移(寄存器):Rd = ASR(Rn, Rm)。
32-bit (sf = 0)
ASR <Wd>, <Wn>, <Wm>
等价指令
ASRV <Wd>, <Wn>, <Wm>
64-bit (sf = 1)
ASR <Xd>, <Xn>, <Xm>
等价指令
ASRV <Xd>, <Xn>, <Xm>
<Wd>
是通用目标寄存器的 32 位名称,在“Rd”字段中编码。
<Wn>
是第一个通用源寄存器的 32 位名称,在“Rn”字段中编码。
<Wm>
是第二个通用源寄存器的 32 位名称,在其底部 5 位中保存从 0 到 31 的移位量,编码在“Rm”字段中。
<Xd>
是通用目标寄存器的 64 位名称,在“Rd”字段中编码。
<Xn>
是第一个通用源寄存器的 64 位名称,在“Rn”字段中编码。
<Xm>
是第二个通用源寄存器的 64 位名称,在其底部 6 位中保存从 0 到 63 的移位量,编码在“Rm”字段中。
下面是使用 ASR(寄存器)指令的例子。
long long int x = -64769;//0xFFFFFFFFFFFF02FFlong long int y = 8;long long int z = 0;asm volatile("ASR %x[z], %x[x], %x[y]\n":[x] "+r"(x),[y] "+r"(y),[z] "+r"(z):: "cc", "memory");
ASR %x[z], %x[x], %x[y]
执行 x 算术右移 y 位,也就是 0xFFFFFFFFFFFF02FF 算术右移 8 位,即最终结果为 0xFFFFFFFFFFFFFF02,所以 z 的最终结果为 -254。算术右移符号位得到了保留!
ASR(立即数)
算术右移(立即数):Rd = ASR(Rn, shift)。
32-bit (sf = 0, N = 0)
ASR <Wd>, <Wn>, #<shift>
等价指令
SBFM <Wd>, <Wn>, #<shift>, #31
64-bit (sf = 1, N = 1)
ASR <Xd>, <Xn>, #<shift>
等价指令
SBFM <Xd>, <Xn>, #<shift>, #63
<Wd>
是通用目标寄存器的 32 位名称,在“Rd”字段中编码。
<Wn>
是通用源寄存器的 32 位名称,在“Rn”字段中编码。
<Xd>
是通用目标寄存器的 64 位名称,在“Rd”字段中编码。
<Xn>
是通用源寄存器的 64 位名称,在“Rn”字段中编码。
<shift>
对于 32 位变体:是移位量,范围为 0 到 31;对于 64 位变体:是移位量,范围为 0 到 63。
下面是使用 ASR(立即数)指令的例子。
long long int x = -64769;//0xFFFFFFFFFFFF02FFlong long int z = 0;asm volatile("ASR %x[z], %x[x], #8\n":[x] "+r"(x),[z] "+r"(z):: "cc", "memory");
ASR %x[z], %x[x], #8
执行 x 算术右移 8 位,也就是 0xFFFFFFFFFFFF02FF 算术右移 8 位,即最终结果为 0xFFFFFFFFFFFFFF02,所以 z 的最终结果为 -254。
2.2 LSL
LSL(寄存器)
逻辑左移(寄存器):Rd = LSL(Rn, Rm)。
32-bit (sf = 0)
LSL <Wd>, <Wn>, <Wm>
等价指令
LSLV <Wd>, <Wn>, <Wm>
64-bit (sf = 1)
LSL <Xd>, <Xn>, <Xm>
等价指令
LSLV <Xd>, <Xn>, <Xm>
<Wd>
是通用目标寄存器的 32 位名称,在“Rd”字段中编码。
<Wn>
是第一个通用源寄存器的 32 位名称,在“Rn”字段中编码。
<Wm>
是第二个通用源寄存器的 32 位名称,在其底部 5 位中保存从 0 到 31 的移位量,编码在“Rm”字段中。
<Xd>
是通用目标寄存器的 64 位名称,在“Rd”字段中编码。
<Xn>
是第一个通用源寄存器的 64 位名称,在“Rn”字段中编码。
<Xm>
是第二个通用源寄存器的 64 位名称,在其底部 6 位中保存从 0 到 63 的移位量,编码在“Rm”字段中。
下面是使用 LSL(寄存器)指令的例子。
long long int x = -64769;//0xFFFFFFFFFFFF02FFlong long int y = 8;long long int z = 0;asm volatile("LSL %x[z], %x[x], %x[y]\n":[x] "+r"(x),[y] "+r"(y),[z] "+r"(z):: "cc", "memory");
LSL %x[z], %x[x], %x[y]
执行 x 逻辑左移 y 位,也就是 0xFFFFFFFFFFFF02FF 逻辑左移 8 位,即最终结果为 0xFFFFFFFFFF02FF00,所以 z 的最终结果为 -16580864。
LSL(立即数)
逻辑左移(立即数):Rd = LSL(Rn, shift)。
32-bit (sf = 0, N = 0)
LSL <Wd>, <Wn>, #<shift>
等价指令
UBFM <Wd>, <Wn>, #(-<shift> MOD 32), #(31-<shift>)
64-bit (sf = 1, N = 1)
LSL <Xd>, <Xn>, #<shift>
等价指令
UBFM <Xd>, <Xn>, #(-<shift> MOD 64), #(63-<shift>)
<Wd>
是通用目标寄存器的 32 位名称,在“Rd”字段中编码。
<Wn>
是通用源寄存器的 32 位名称,在“Rn”字段中编码。
<Xd>
是通用目标寄存器的 64 位名称,在“Rd”字段中编码。
<Xn>
是通用源寄存器的 64 位名称,在“Rn”字段中编码。
<shift>
对于 32 位变体:是移位量,范围为 0 到 31;对于 64 位变体:是移位量,范围为 0 到 63。
下面是使用 LSL(立即数)指令的例子。
long long int x = -64769;//0xFFFFFFFFFFFF02FFlong long int z = 0;asm volatile("LSL %x[z], %x[x], #8\n":[x] "+r"(x),[z] "+r"(z):: "cc", "memory");
LSL %x[z], %x[x], #8
执行 x 逻辑左移 8 位,也就是 0xFFFFFFFFFFFF02FF 逻辑左移 8 位,即最终结果为 0xFFFFFFFFFF02FF00,所以 z 的最终结果为 -16580864。
2.3 LSR
LSR(寄存器)
逻辑右移(寄存器):Rd = LSR(Rn, Rm)。
32-bit (sf = 0)
LSR <Wd>, <Wn>, <Wm>
等价指令
LSRV <Wd>, <Wn>, <Wm>
64-bit (sf = 1)
LSR <Xd>, <Xn>, <Xm>
等价指令
LSRV <Xd>, <Xn>, <Xm>
<Wd>
是通用目标寄存器的 32 位名称,在“Rd”字段中编码。
<Wn>
是第一个通用源寄存器的 32 位名称,在“Rn”字段中编码。
<Wm>
是第二个通用源寄存器的 32 位名称,在其底部 5 位中保存从 0 到 31 的移位量,编码在“Rm”字段中。
<Xd>
是通用目标寄存器的 64 位名称,在“Rd”字段中编码。
<Xn>
是第一个通用源寄存器的 64 位名称,在“Rn”字段中编码。
<Xm>
是第二个通用源寄存器的 64 位名称,在其底部 6 位中保存从 0 到 63 的移位量,编码在“Rm”字段中。
下面是使用 LSR(寄存器)指令的例子。
long long int x = -64769;//0xFFFFFFFFFFFF02FFlong long int y = 8;long long int z = 0;asm volatile("LSR %x[z], %x[x], %x[y]\n":[x] "+r"(x),[y] "+r"(y),[z] "+r"(z):: "cc", "memory");
LSR %x[z], %x[x], %x[y]
执行 x 逻辑右移 y 位,也就是 0xFFFFFFFFFFFF02FF 逻辑右移 8 位,即最终结果为 0x00FFFFFFFFFFFF02,所以 z 的最终结果为 72057594037927682。
LSR(立即数)
逻辑右移(立即数):Rd = LSR(Rn, shift)。
32-bit (sf = 0, N = 0)
LSR <Wd>, <Wn>, #<shift>
等价指令
UBFM <Wd>, <Wn>, #<shift>, #31
64-bit (sf = 1, N = 1)
LSR <Xd>, <Xn>, #<shift>
等价指令
UBFM <Xd>, <Xn>, #<shift>, #63
<Wd>
是通用目标寄存器的 32 位名称,在“Rd”字段中编码。
<Wn>
是通用源寄存器的 32 位名称,在“Rn”字段中编码。
<Xd>
是通用目标寄存器的 64 位名称,在“Rd”字段中编码。
<Xn>
是通用源寄存器的 64 位名称,在“Rn”字段中编码。
<shift>
对于 32 位变体:是移位量,范围为 0 到 31;对于 64 位变体:是移位量,范围为 0 到 63。
下面是使用 LSR(立即数)指令的例子。
long long int x = -64769;//0xFFFFFFFFFFFF02FFlong long int z = 0;asm volatile("LSR %x[z], %x[x], #8\n":[x] "+r"(x),[z] "+r"(z):: "cc", "memory");
LSR %x[z], %x[x], #8
执行 x 逻辑右移 8 位,也就是 0xFFFFFFFFFFFF02FF 逻辑右移 8 位,即最终结果为 0x00FFFFFFFFFFFF02,所以 z 的最终结果为 72057594037927682。
2.4 ROR
ROR(寄存器)
循环右移(寄存器):Rd = ROR(Rn, Rm)。
32-bit (sf = 0)
ROR <Wd>, <Wn>, <Wm>
等价指令
RORV <Wd>, <Wn>, <Wm>
64-bit (sf = 1)
ROR <Xd>, <Xn>, <Xm>
等价指令
RORV <Xd>, <Xn>, <Xm>
<Wd>
是通用目标寄存器的 32 位名称,在“Rd”字段中编码。
<Wn>
是第一个通用源寄存器的 32 位名称,在“Rn”字段中编码。
<Wm>
是第二个通用源寄存器的 32 位名称,在其底部 5 位中保存从 0 到 31 的移位量,编码在“Rm”字段中。
<Xd>
是通用目标寄存器的 64 位名称,在“Rd”字段中编码。
<Xn>
是第一个通用源寄存器的 64 位名称,在“Rn”字段中编码。
<Xm>
是第二个通用源寄存器的 64 位名称,在其底部 6 位中保存从 0 到 63 的移位量,编码在“Rm”字段中。
下面是使用 ROR(寄存器)指令的例子。
long long int x = 255;//0xFFlong long int y = 8;long long int z = 0;asm volatile("ROR %x[z], %x[x], %x[y]\n":[x] "+r"(x),[y] "+r"(y),[z] "+r"(z):: "cc", "memory");
ROR %x[z], %x[x], %x[y]
执行 x 循环右移 y 位,也就是 0xFF 循环右移 8 位,即最终结果为 0xFF00000000000000,所以 z 的最终结果为 -72057594037927936。
ROR(立即数)
逻辑右移(立即数):Rd = ROR(Rs, shift)。
32-bit (sf = 0, N = 0, imms = 0xxxxx)
ROR <Wd>, <Ws>, #<shift>
等价指令
EXTR <Wd>, <Ws>, <Ws>, #<shift>
64-bit (sf = 1, N = 1)
ROR <Xd>, <Xs>, #<shift>
等价指令
EXTR <Xd>, <Xs>, <Xs>, #<shift>
<Wd>
是通用目标寄存器的 32 位名称,在“Rd”字段中编码。
<Ws>
是通用源寄存器的 32 位名称,编码在“Rn”和“Rm”字段中。
<Xd>
是通用目标寄存器的 64 位名称,在“Rd”字段中编码。
<Xs>
是通用源寄存器的 64 位名称,在“Rn”和“Rm”字段中编码。
<shift>
对于 32 位变体:是循环移位的量,在 0 到 31 的范围内,编码在“imms”字段中;对于 64 位变体:是在 0 到 63 范围内循环移位的量,编码在“imms”字段中。
下面是使用 ROR(立即数)指令的例子。
long long int x = 255;//0xFFlong long int z = 0;asm volatile("ROR %x[z], %x[x], #8\n":[x] "+r"(x),[z] "+r"(z):: "cc", "memory");
ROR %x[z], %x[x], #8
执行 x 循环右移 8 位,也就是 0xFF 循环右移 8 位,即最终结果为 0xFF00000000000000,所以 z 的最终结果为 -72057594037927936。
参考资料
1.《ARMv8-A-Programmer-Guide》
2.《Arm® A64 Instruction Set Architecture Armv8, for Armv8-A architecture profile》
【ARMv8 编程】A64 数据处理指令——逻辑移位指令相关推荐
- 【ARMv8 编程】A64 数据处理指令——算术指令
许多在应用程序级别编写代码的程序员不需要用汇编语言编写代码.然而,汇编代码在需要高度优化的代码的情况下很有用.在编写编译器时,或者需要使用 C 语言中无法直接提供的底层特性时,都会出现这种情况.部分引 ...
- 【ARMv8 编程】A64 数据处理指令——移动比较指令
移动指令主要为 MOV 以及它的各种"变体",而比较指令主要用来进行比较并更新条件标志,用来实现条件判断等. 指令类型 指令 移动 MOV.MVN.MOVK.MOVZ.MOVN 比 ...
- 【ARMv8 编程】A64 数据处理指令——位域字节操作指令
有些指令将字节.半字或字扩展到寄存器大小,可以是 X 或 W.这些指令存在于有符号(SXTB.SXTH.SXTW)和无符号(UXTB.UXTH)变体中,并且是适当的位域操作指令. 这些指令的有符号和无 ...
- 【ARMv8 编程】A64 内存访问指令——内存加载指令
与所有先前的 ARM 处理器一样,ARMv8 架构是一种加载/存储架构.这意味着没有数据处理指令直接对内存中的数据进行操作.数据必须首先被加载到寄存器中,修改,然后存储到内存中.该程序必须指定地址.要 ...
- 【ARMv8 SIMD和浮点指令编程】编程基础
ARM 高级 SIMD 架构.相关的实现和支持软件通常被称为 NEON 技术.AArch32(相当于 ARMv7 的 NEON 指令)和 AArch64 都有 NEON 指令集.两者都可以显著加速在大 ...
- 三,位操作类指令:包括逻辑运算指令,测试指令和移位指令
1,测试运算指令:有四条,其格式与功能本别为: 与: AND DEST,SRC EDST <= (SRC) ^(DEST) 或:OR DEST,SRC DEST <= (SRC) v (D ...
- ARMv8体系结构基础04:算术和移位指令
目录 1 数据处理指令概述 2 加法指令详解 2.1 ADD指令 2.1.1 ADD(extended register)指令编码分析 2.1.2 ADD(extended register)指令编码 ...
- 【ARMv8 编程】寄存器
ARMv8 用于描述整体架构,包括 32 位执行和 64 位执行.它使用 64 位位宽寄存器,同时保持向后兼容 v7. 现在来看看 ARMv8 都有哪些改进: 大的物理地址 这使处理器能够访问超过 4 ...
- 【汇编语言】通用数据处理指令——位操作类指令
通用数据处理指令--位操作类指令 文章目录 通用数据处理指令--位操作类指令 一.逻辑运算指令 1.逻辑与指令AND 2.逻辑或指令OR 3.逻辑非指令NOT 4.逻辑异或指令XOR 5.逻辑运算的应 ...
最新文章
- Javascript 节点 全面解析
- 苹果发布会体现出的未来趋势
- python如何编程-终于发现怎么自学python编程
- 【LeetCode】376. 摆动序列(图解)
- 怎么检测mysql卸载完全_怎么检查mysql有没有删干净
- android怎么关应用程序,如何关闭Android应用程序?
- final,finally,finaliz的区别(Java)
- vuecli3+webpack4优化实践(删除console.log和配置dllPlugin)
- 在X++中使用IoC/DI模式应对不断变化的客户需求
- GitLab 配置 OAuth2 实现第三方登录,简直太方便了!
- 严蔚敏版《数据结构 (C语言版)》和《数据结构题集》(五)——栈和队列...
- 双层卷积神经网络--tf
- php gtk 中文手册,PHP-GTK
- 学生免费获取PyCharm专业版
- html 设置div背景颜色,CSS设置网页背景颜色技术教程篇
- 汽车CAN 总线系统原理设计与应用 (一)
- LCD带字符液晶显示I LOVE YOU
- 自律的力量 No Excuse: the power of self-discipline
- 深富策略市场情绪明显回暖
- 2017-11-20 白银解说