【ARMv8 编程】A64 数据处理指令——逻辑&移位指令

本文详细介绍了ARMv8-A架构中的逻辑指令,包括AND、BIC、ORR、ORN、EOR和EON,以及移位指令ASR、LSL、LSR和ROR的操作和用法,通过实例展示了这些指令如何对寄存器中的位进行操作和移位计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

逻辑指令包括与、或等指令,移位指令则分为逻辑移位和算术移位指令,下面则详细展开学习。

指令类型指令
逻辑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 字段取值
LSLshift = 00
LSRshift = 01
ASRshift = 10
RORshift = 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 字段取值
LSLshift = 00
LSRshift = 01
ASRshift = 10
RORshift = 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 字段取值
LSLshift = 00
LSRshift = 01
ASRshift = 10
RORshift = 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 字段取值
LSLshift = 00
LSRshift = 01
ASRshift = 10
RORshift = 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 字段取值
LSLshift = 00
LSRshift = 01
ASRshift = 10
RORshift = 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 字段取值
LSLshift = 00
LSRshift = 01
ASRshift = 10
RORshift = 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》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TYYJ-洪伟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值