逻辑指令包括与、或等指令,移位指令则分为逻辑移位和算术移位指令,下面则详细展开学习。
指令类型 | 指令 |
---|---|
逻辑 | 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;//108
long long int y = 0b00110000;//48
long 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;//108
long 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;//108
long long int y = 0b00110000;//48
long 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;//108
long long int y = 0b00110000;//48
long 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;//108
long 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;//108
long long int y = 0b00110000;//48
long 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;//108
long long int y = 0b00110000;//48
long 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;//0xFFFFFFFFFFFF02FF
long 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;//0xFFFFFFFFFFFF02FF
long 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;//0xFFFFFFFFFFFF02FF
long 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;//0xFFFFFFFFFFFF02FF
long 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;//0xFFFFFFFFFFFF02FF
long 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;//0xFFFFFFFFFFFF02FF
long 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;//0xFF
long 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;//0xFF
long 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》