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

news/2024/6/18 21:57:27 标签: 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 字段取值
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》


http://www.niftyadmin.cn/n/189712.html

相关文章

堆(数据结构系列11)

目录 前言&#xff1a; 1.优先级队列概念 2.堆的概念 3.堆的存储方式 4.堆的创建 5.创建堆的时间复杂度 6.堆的插入和删除 6.1堆的插入 6.2堆的删除 结束语&#xff1a; 前言&#xff1a; 上一次博客中小编主要与大家分享了 二叉树一些相关的知识点和一些练习题&…

射频接收机概述

接收机架构 射频接收机架构是指电子设备中用于接收无线电信号的部分。它通常由前置放大器、中频放大器、混频器、局部振荡器和带通滤波器等组成。以下是一个基本的射频接收机架构&#xff1a; 前置放大器&#xff1a;前置放大器的作用是放大接收天线接收到的微弱无线电信号&am…

java入门-W2

一. 输入输出 输入的作用&#xff0c;就是由使用者告诉程序要操作的数据 例如&#xff0c;我要通过饿了么订餐&#xff0c;你得告诉程序你要吃什么&#xff0c;送货地址是什么吧 输出的作用&#xff0c;就是由程序向使用者展现执行的结果 还是订餐的例子&#xff0c;程序向你展…

SpringBoot中日志的使用

springboot 默认就是使用SLF4J作为日志门面&#xff0c;logback作为日志实现来记录日志的 文章目录1. SpringBoot 中的日志设计2. SpringBoot 日志使用1. SpringBoot 中的日志设计 springboot中的日志 <dependency><artifactId>spring-boot-starter-logging</…

strlen和sizeof

#include <stdio.h>int main() {char *p1NULL;printf("strlen(p1)%d\n",strlen(p1));return 0; }编译会提醒但不会报错&#xff0c;运行报段错误 #include <stdio.h>int main() {char *p1NULL;printf("sizeof(p1)%d\n",sizeof(p1));return 0;…

coquiTTS官网帮助文档

官网文档&#xff1a; Synthesizing Speech - TTS 0.12.0 documentation 基本参数解释 coquiTTS&#xff0c;github地址 https://github.com/coqui-ai 里面有http服务配置&#xff0c;待测试 常用命令 1&#xff0c;切换conda环境 conda activate xxx 2&#xff0c;列出可…

MySQL图形化工具DBeaver下载安装与连接MySQL步骤详解

一、命令行环境下操作MySQL 1.1 进入MySQL “winr”输入“cmd”&#xff0c;点击确认&#xff0c;打开命令提示符&#xff0c;输入命令“mysql -uroot -p”后&#xff0c;输入密码&#xff1b; 1.2 进行简单操作 1.2.1 查看有哪些数据库&#xff1a;show databases; 1.2.2 …

windows 下C++生成Dump调试文件与分析

目录1、前言2、依赖库下载3、项目配置3.1、设置输出路径3.2、拷贝依赖资源3.3 将dbghelp.h添加在工程中3.4、配置lib文件路径3.5、添加生成minidump文件方法4、测试效果5、打开dump文件进行定位1、前言 dump文件是C程序发生异常时&#xff0c;保存当时程序运行状态的文件&…