【ARMv8 编程】A64 数据处理指令——位域字节操作指令

news2024/11/9 1:39:39

有些指令将字节、半字或字扩展到寄存器大小,可以是 X 或 W。这些指令存在于有符号(SXTB、SXTH、SXTW)和无符号(UXTB、UXTH)变体中,并且是适当的位域操作指令。

这些指令的有符号和无符号变体都将字节、半字或字(尽管只有 SXTW 对字进行操作)扩展到寄存器大小。源始终是 W 寄存器。目标寄存器是 X 或 W 寄存器,但 SXTW 除外,它必须是 X 寄存器。

例如:SXTB X0, W1 —— 通过重复字节的最左边的位,将寄存器 W1 的最低有效字节从 8 位符号扩展为 64 位。

位域指令类似于 ARMv7 中存在的指令,包括位域插入 (BFI) 以及有符号和无符号位域提取 ((S/U)BFX)。还有额外的位域指令,例如 BFXIL(低位域提取和插入)、UBFIZ(无符号位域插入零)和 SBFIZ(有符号位域插入零)。

还有 BFM、UBFM 和 SBFM 指令。 这些是 ARMv8 新增的位域移动指令。但是,不需要明确使用这些指令,因为为所有情况提供了别名。这些别名是已经描述的位域操作:[SU]XT[BHWX]、ASR/LSL/LSR immediate、BFI、BFXIL、SBFIZ、SBFX、UBFIZ 和 UBFX。

CLZ —— 计数寄存器中的前导零位。

RBIT —— 反转所有位。

REV —— 反转寄存器的字节顺序。

REV16 —— 反转寄存器中每个半字的字节顺序。

REV32 —— 反转寄存器中每个字的字节顺序。

REV、REV16、可以在字(32 位)或双字(64 位)大小的寄存器上执行,REV32 仅适用于 64 位寄存器。

1. SXTB

SXTB(Signed Extend Byte)指令从寄存器中提取一个 8 位值,将其符号扩展到寄存器的大小,并将结果写入目标寄存器。该指令是 SBFM 指令的别名。

在这里插入图片描述

32-bit (sf == 0 && N == 0)

SXTB <Wd>, <Wn>

等价指令

SBFM <Wd>, <Wn>, #0, #7

64-bit (sf == 1 && N == 1)

SXTB <Xd>, <Wn>

等价指令

SBFM <Xd>, <Xn>, #0, #7

<Wd> 是通用目标寄存器的 32 位名称,在“Rd”字段中编码。

<Xd> 是通用目标寄存器的 64 位名称,在“Rd”字段中编码。

<Xn> 是通用源寄存器的 64 位名称,在“Rn”字段中编码。

<Wn> 是通用源寄存器的 32 位名称,在“Rn”字段中编码。

下面是使用 SXTB 指令的例子。

    long long int x = 0;
    int y = 0x7080;

    asm volatile(
        "SXTB %x[x], %w[y]\n"
    :[x] "+r"(x),
    [y] "+r"(y)
    :
    : "cc", "memory");

执行 SXTB %x[x], %w[y]%w[y] 的最低 8 位符号扩展为 64 位,也就是 0x7080 中的 0x80(0b1000 0000)符号位为 1,扩展到 64 位,即 0xFFFF FFFF FFFF FF80,十进制为 -128,这也是最终 x 的值。

2. SXTH

SXTH(Sign Extend Halfword —— 符号扩展半字)指令提取一个 16 位值,将其符号扩展到寄存器的大小,并将结果写入目标寄存器。该指令是 SBFM 指令的别名。

在这里插入图片描述

32-bit (sf == 0 && N == 0)

SXTH <Wd>, <Wn>

等价指令

SBFM <Wd>, <Wn>, #0, #15

64-bit (sf == 1 && N == 1)

SXTH <Xd>, <Wn>

等价指令

SBFM <Xd>, <Xn>, #0, #15

<Wd> 是通用目标寄存器的 32 位名称,在“Rd”字段中编码。

<Xd> 是通用目标寄存器的 64 位名称,在“Rd”字段中编码。

<Xn> 是通用源寄存器的 64 位名称,在“Rn”字段中编码。

<Wn> 是通用源寄存器的 32 位名称,在“Rn”字段中编码。

下面是使用 SXTH 指令的例子。

    long long int x = 0;
    int y = 0x7080;

    asm volatile(
        "SXTH %x[x], %w[y]\n"
    :[x] "+r"(x),
    [y] "+r"(y)
    :
    : "cc", "memory");

执行 SXTH %x[x], %w[y]%w[y] 的最低 16 位符号扩展为 64 位,也就是 0x7080 中的 0x7080(0b0111 0000 1000 0000)符号位为 0,扩展到 64 位,还是 0x7080,十进制为 28800,这也是最终 x 的值。

3. SXTW

SXTW(Sign Extend Word —— 符号扩展字)指令将一个字符号扩展到寄存器的大小,并将结果写入目标寄存器。该指令是 SBFM 指令的别名。

在这里插入图片描述

64-bit

SXTW <Xd>, <Wn>

等价指令

SBFM <Xd>, <Xn>, #0, #31

<Xd> 是通用目标寄存器的 64 位名称,在“Rd”字段中编码。

<Xn> 是通用源寄存器的 64 位名称,在“Rn”字段中编码。

<Wn> 是通用源寄存器的 32 位名称,在“Rn”字段中编码。

下面是使用 SXTW 指令的例子。

    long long int x = 0;
    int y = 0x7080;

    asm volatile(
        "SXTW %x[x], %w[y]\n"
    :[x] "+r"(x),
    [y] "+r"(y)
    :
    : "cc", "memory");

执行 SXTW %x[x], %w[y]%w[y] 符号扩展为 64 位,也就是 0x7080 中的 0x7080(0b0000 0000 0000 0000 0111 0000 1000 0000)符号位为 0,扩展到 64 位,还是 0x7080,十进制为 28800,这也是最终 x 的值。

4. UXTB

UXTB(Unsigned Extend Byte —— 无符号扩展字节) 从寄存器中提取一个 8 位值,将其零扩展到寄存器的大小,并将结果写入目标寄存器。该指令是 UBFM 指令的别名。

在这里插入图片描述

32-bit

UXTB <Wd>, <Wn>

等价指令

UBFM <Wd>, <Wn>, #0, #7

<Wd> 是通用目标寄存器的 32 位名称,在“Rd”字段中编码。

<Wn> 是通用源寄存器的 32 位名称,在“Rn”字段中编码。

下面是使用 UXTB 指令的例子。

    int x = 0;
    int y = 0x7080;

    asm volatile(
        "UXTB %w[x], %w[y]\n"
    :[x] "+r"(x),
    [y] "+r"(y)
    :
    : "cc", "memory");

执行 UXTB %w[x], %w[y]%w[y] 扩展为 32 位,也就是 0x7080 中的 0x80(0b1000 0000)扩展到 32 位(以零填充扩展位),最终还为 0x80,这也是最终 x 的值。

5. UXTH

UXTH(Unsigned Extend Halfword —— 无符号扩展半字) 从寄存器中提取一个 16 位值,将其零扩展到寄存器的大小,并将结果写入目标寄存器。该指令是 UBFM 指令的别名。

在这里插入图片描述

32-bit

UXTH <Wd>, <Wn>

等价指令

UBFM <Wd>, <Wn>, #0, #15

<Wd> 是通用目标寄存器的 32 位名称,在“Rd”字段中编码。

<Wn> 是通用源寄存器的 32 位名称,在“Rn”字段中编码。

下面是使用 UXTH 指令的例子。

    int x = 0;
    int y = 0x77777080;

    asm volatile(
        "UXTH %w[x], %w[y]\n"
    :[x] "+r"(x),
    [y] "+r"(y)
    :
    : "cc", "memory");

执行 UXTH %w[x], %w[y]%w[y] 扩展为 32 位,也就是 0x77777080 的低 16 位,即 0x7080(0b0111 0000 1000 0000)扩展到 32 位(以零填充扩展位),最终还为 0x7080,这也是最终 x 的值。

6. BFI

BFI(Bitfield Insert —— 位域插入)指令将 <width> 位的位域从源寄存器的最低有效位复制到目标寄存器的位位置 <lsb>,而其他目标位保持不变。该指令是 BFM 指令的别名。

在这里插入图片描述

32-bit (sf == 0 && N == 0)

BFI <Wd>, <Wn>, #<lsb>, #<width>

等价指令

BFM <Wd>, <Wn>, #(-<lsb> MOD 32), #(<width>-1)

64-bit (sf == 1 && N == 1)

BFI <Xd>, <Xn>, #<lsb>, #<width>

等价指令

BFM <Xd>, <Xn>, #(-<lsb> MOD 64), #(<width>-1)

<Wd> 是通用目标寄存器的 32 位名称,在“Rd”字段中编码。

<Wn> 是通用源寄存器的 32 位名称,在“Rn”字段中编码。

<Xd> 是通用目标寄存器的 64 位名称,在“Rd”字段中编码。

<Xn> 是通用源寄存器的 64 位名称,在“Rn”字段中编码。

<lsb> 对于 32 位变体:是目标位域的 lsb 的位数,范围为 0 到 31。对于 64 位变体:是目标位域的 lsb 的位数,范围为 0 到 63。

<width> 对于 32 位变体:是位域的宽度,范围为 1 到 32-<lsb>。对于 64 位变体:是位域的宽度,范围为 1 到 64-<lsb>

下图是 BFI W0, W0, #9, #6 指令操作示意图:

在这里插入图片描述

下面是使用 BFI 指令的例子。

    long long int x = -1;
    long long int y = 0x77777080;

    asm volatile(
        "BFI %x[x], %x[y], #16, #16\n"
    :[x] "+r"(x),
    [y] "+r"(y)
    :
    : "cc", "memory");

执行 BFI %x[x], %x[y], #16, #16%x[y] 最低 16 位复制到 %x[x] 的 16 ~ 31 位,也就是 0x77777080 的低 16 位,即 0x7080(0b0111 0000 1000 0000)复制到 %x[x] 的 16 ~ 31 位,最终的结果就是 0xFFFF FFFF 7080 FFFF,这也是最终 x 的值。

7. BFC

BFC(Bitfield Clear —— 位域清零) 将目标寄存器的位位置 <lsb> 处的 <width> 位的位域设置为零,而其他目标位保持不变。该指令是 BFM 指令的别名。

在这里插入图片描述

32-bit (sf == 0 && N == 0)

BFC <Wd>, #<lsb>, #<width>

等价指令

BFM <Wd>, WZR, #(-<lsb> MOD 32), #(<width>-1)

64-bit (sf == 1 && N == 1)

BFC <Xd>, #<lsb>, #<width>

等价指令

BFM <Xd>, XZR, #(-<lsb> MOD 64), #(<width>-1)

<Wd> 是通用目标寄存器的 32 位名称,在“Rd”字段中编码。

<Xd> 是通用目标寄存器的 64 位名称,在“Rd”字段中编码。

<lsb> 对于 32 位变体:是目标位域的 lsb 的位数,范围为 0 到 31。对于 64 位变体:是目标位域的 lsb 的位数,范围为 0 到 63。

<width> 对于 32 位变体:是位域的宽度,范围为 1 到 32-<lsb>。对于 64 位变体:是位域的宽度,范围为 1 到 64-<lsb>

下图是 BFC W1, #3, #4 指令操作示意图:

在这里插入图片描述

下面是使用 BFC 指令的例子。

    long long int x = -1;

    asm volatile(
        "BFC %x[x], #8, #8\n"
    :[x] "+r"(x)
    :
    : "cc", "memory");

执行 BFC %x[x], #8, #8%x[x] 寄存器的 8 ~ 15 位(宽度为 8)清零,即 0xFFFF FFFF FFFF 00FF,这也是最终 x 的值。

8. SBFX

SBFX(Signed Bitfield Extract —— 有符号位域提取) 指令复制一个 <width> 位的位域,从源寄存器中的位位置 <lsb> 开始到目标寄存器的最低有效位,并将位域前面的目标位设置为位域最高有效位的副本。该指令是 SBFM 指令的别名。

在这里插入图片描述

32-bit (sf == 0 && N == 0)

SBFX <Wd>, <Wn>, #<lsb>, #<width>

等价指令

SBFM <Wd>, <Wn>, #<lsb>, #(<lsb>+<width>-1)

64-bit (sf == 1 && N == 1)

SBFX <Xd>, <Xn>, #<lsb>, #<width>

等价指令

SBFM <Xd>, <Xn>, #<lsb>, #(<lsb>+<width>-1)

<Wd> 是通用目标寄存器的 32 位名称,在“Rd”字段中编码。

<Wn> 是通用源寄存器的 32 位名称,在“Rn”字段中编码。

<Xd> 是通用目标寄存器的 64 位名称,在“Rd”字段中编码。

<Xn> 是通用源寄存器的 64 位名称,在“Rn”字段中编码。

<lsb> 对于 32 位变体:是源位域的 lsb 的位数,范围为 0 到 31。对于 64 位变体:是源位域的 lsb 的位数,范围为 0 到 63。

<width> 对于 32 位变体:是位域的宽度,范围为 1 到 32-<lsb>。对于 64 位变体:是位域的宽度,范围为 1 到 64-<lsb>

下面是使用 SBFX 指令的例子。

    long long int x = 0;
    long long int y = 0x87;

    asm volatile(
        "SBFX %x[x], %x[y], #4, #4\n"
    :[x] "+r"(x),
     [y] "+r"(y)
    :
    : "cc", "memory");

执行 SBFX %x[x], %x[y], #4, #4,首先将 %x[y] 寄存器内的 0x87 的 4 ~ 7 位复制到 %x[x] 寄存器的 0 ~ 3 位,又因为 0x87 的第七位为 1,所以使用 1 扩展 %x[x] 的 4 ~ 63 位(这里体现了符号位),即 0xFFFF FFFF FFFF FF80,这也是最终 x 的值。

9. UBFX

UBFX(Unsigned Bitfield Extract —— 无符号位域提取)指令复制一个 <width> 位的位域,从源寄存器中的位位置 <lsb> 开始到目标寄存器的最低有效位,并将位域前面的目标位设置为零。该指令是 UBFM 指令的别名。

在这里插入图片描述

32-bit (sf == 0 && N == 0)

UBFX <Wd>, <Wn>, #<lsb>, #<width>

等价指令

UBFM <Wd>, <Wn>, #<lsb>, #(<lsb>+<width>-1)

64-bit (sf == 1 && N == 1)

UBFX <Xd>, <Xn>, #<lsb>, #<width>

等价指令

UBFM <Xd>, <Xn>, #<lsb>, #(<lsb>+<width>-1)

<Wd> 是通用目标寄存器的 32 位名称,在“Rd”字段中编码。

<Wn> 是通用源寄存器的 32 位名称,在“Rn”字段中编码。

<Xd> 是通用目标寄存器的 64 位名称,在“Rd”字段中编码。

<Xn> 是通用源寄存器的 64 位名称,在“Rn”字段中编码。

<lsb> 对于 32 位变体:是源位域的 lsb 的位数,范围为 0 到 31。对于 64 位变体:是源位域的 lsb 的位数,范围为 0 到 63。

<width> 对于 32 位变体:是位域的宽度,范围为 1 到 32-<lsb>。对于 64 位变体:是位域的宽度,范围为 1 到 64-<lsb>

下图是 UBFX W1, W0, #18, #7 指令操作示意图:

在这里插入图片描述

下面是使用 UBFX 指令的例子。

    long long int x = 0;
    long long int y = 0x87;

    asm volatile(
        "UBFX %x[x], %x[y], #4, #4\n"
    :[x] "+r"(x),
     [y] "+r"(y)
    :
    : "cc", "memory");

执行 UBFX %x[x], %x[y], #4, #4,首先将 %x[y] 寄存器内的 0x87 的 4 ~ 7 位复制到 %x[x] 寄存器的 0 ~ 3 位,接着使用 0 扩展 %x[x] 的 4 ~ 63 位,即 0x8,这也是最终 x 的值。

10. BFXIL

位域提取并在低端插入,其他位不变。该指令是 BFM 指令的别名。

在这里插入图片描述

32-bit (sf == 0 && N == 0)

BFXIL <Wd>, <Wn>, #<lsb>, #<width>

等价指令

BFM <Wd>, <Wn>, #<lsb>, #(<lsb>+<width>-1)

64-bit (sf == 1 && N == 1)

BFXIL <Xd>, <Xn>, #<lsb>, #<width>

等价指令

BFM <Xd>, <Xn>, #<lsb>, #(<lsb>+<width>-1)

<Wd> 是通用目标寄存器的 32 位名称,在“Rd”字段中编码。

<Wn> 是通用源寄存器的 32 位名称,在“Rn”字段中编码。

<Xd> 是通用目标寄存器的 64 位名称,在“Rd”字段中编码。

<Xn> 是通用源寄存器的 64 位名称,在“Rn”字段中编码。

<lsb> 是源位域的“lsb”的位数。对于 32 位变体:范围为 0 到 31;对于 64 位变体:范围为 0 到 63。

<width> 是位域的宽度。对于 32 位变体:范围为 1 到 32-<lsb>;对于 64 位变体:范围为 1 到 64-<lsb>

下面是使用 BFXIL 指令的例子。

    long long int x = 0x4444;
    long long int y = 0x87;

    asm volatile(
        "BFXIL %x[x], %x[y], #4, #4\n"
    :[x] "+r"(x),
     [y] "+r"(y)
    :
    : "cc", "memory");

执行 BFXIL %x[x], %x[y], #4, #4,首先将 %x[y] 寄存器内的 0x87 的 4 ~ 7 位复制到 %x[x] 寄存器的 0 ~ 3 位,其它位保持不变,所以最终 %x[x] 的值为 0x4448。

11. UBFIZ

无符号位域插入零,左右为零。该指令是 UBFM 指令的别名。

在这里插入图片描述

32-bit (sf == 0 && N == 0)

UBFIZ <Wd>, <Wn>, #<lsb>, #<width>

等价指令

UBFM <Wd>, <Wn>, #(-<lsb> MOD 32), #(<width>-1)

64-bit (sf == 1 && N == 1)

UBFIZ <Xd>, <Xn>, #<lsb>, #<width>

等价指令

UBFM <Xd>, <Xn>, #(-<lsb> MOD 64), #(<width>-1)

<Wd> 是通用目标寄存器的 32 位名称,在“Rd”字段中编码。

<Wn> 是通用源寄存器的 32 位名称,在“Rn”字段中编码。

<Xd> 是通用目标寄存器的 64 位名称,在“Rd”字段中编码。

<Xn> 是通用源寄存器的 64 位名称,在“Rn”字段中编码。

<lsb> 是源位域的“lsb”的位数。对于 32 位变体:范围为 0 到 31;对于 64 位变体:范围为 0 到 63。

<width> 是位域的宽度。对于 32 位变体:范围为 1 到 32-<lsb>;对于 64 位变体:范围为 1 到 64-<lsb>

下面是使用 UBFIZ 指令的例子。

    long long int x = 0x444444;
    long long int y = 0x89;

    asm volatile(
        "UBFIZ %x[x], %x[y], #8, #8\n"
    :[x] "+r"(x),
    [y] "+r"(y)
    :
    : "cc", "memory");

执行 UBFIZ %x[x], %x[y], #8, #8,首先将 %x[y] 寄存器内的 0x89 低 8 位复制到 %x[x] 寄存器的 8 ~ 15 位,其它位全部清零,所以最终 %x[x] 的值为 0x8900。

12. SBFIZ

带符号的位域插入零,符号复制到左边,零复制到右边。该指令是 SBFM 指令的别名。

在这里插入图片描述

32-bit (sf == 0 && N == 0)

SBFIZ <Wd>, <Wn>, #<lsb>, #<width>

等价指令

SBFM <Wd>, <Wn>, #(-<lsb> MOD 32), #(<width>-1)

64-bit (sf == 1 && N == 1)

SBFIZ <Xd>, <Xn>, #<lsb>, #<width>

等价指令

SBFM <Xd>, <Xn>, #(-<lsb> MOD 64), #(<width>-1)

<Wd> 是通用目标寄存器的 32 位名称,在“Rd”字段中编码。

<Wn> 是通用源寄存器的 32 位名称,在“Rn”字段中编码。

<Xd> 是通用目标寄存器的 64 位名称,在“Rd”字段中编码。

<Xn> 是通用源寄存器的 64 位名称,在“Rn”字段中编码。

<lsb> 是源位域的“lsb”的位数。对于 32 位变体:范围为 0 到 31;对于 64 位变体:范围为 0 到 63。

<width> 是位域的宽度。对于 32 位变体:范围为 1 到 32-<lsb>;对于 64 位变体:范围为 1 到 64-<lsb>

下面是使用 SBFIZ 指令的例子。

    long long int x = 0x444444;
    long long int y = 0x89;

    asm volatile(
        "SBFIZ %x[x], %x[y], #8, #8\n"
    :[x] "+r"(x),
    [y] "+r"(y)
    :
    : "cc", "memory");

执行 SBFIZ %x[x], %x[y], #8, #8,首先将 %x[y] 寄存器内的 0x89 低 8 位复制到 %x[x] 寄存器的 8 ~ 15 位,接着由于 0x89 符号位为 1,所以 16 ~ 63 位全部复制为 1, 0 ~ 7 位则清零,所以最终 %x[x] 的值为 0xFFFF FFFF FFFF 8900。

13. BFM

BFM(Bitfield move —— 位域移动)位域移动,其他位不变。该指令由别名 BFC、BFI 和 BFXIL 使用。

  • 如果 <imms> 大于或等于 <immr>,则将从源寄存器中的位位置 <immr> 开始的(<imms> - <immr> + 1)位的位域复制到目标寄存器的最低有效位。

  • 如果 <imms> 小于<immr>,则将源寄存器的最低有效位中的(<imms> + 1)位的位域复制到目标寄存器的位位置(regsize - <immr>),其中 regsize 是 32 或 64 位的目标寄存器大小。

在这两种情况下,目的寄存器的其他位保持不变。

在这里插入图片描述

32-bit (sf == 0 && N == 0)

BFM <Wd>, <Wn>, #<immr>, #<imms>

64-bit (sf == 1 && N == 1)

BFM <Xd>, <Xn>, #<immr>, #<imms>

<Wd> 是通用目标寄存器的 32 位名称,在“Rd”字段中编码。

<Wn> 是通用源寄存器的 32 位名称,在“Rn”字段中编码。

<Xd> 是通用目标寄存器的 64 位名称,在“Rd”字段中编码。

<Xn> 是通用源寄存器的 64 位名称,在“Rn”字段中编码。

<immr> 是循环右移量,在“immr”字段中编码。对于 32 位变体:在 0 到 31 的范围内;对于 64 位变体:是在 0 到 63 范围内。

<imms> 是要从源移动的最左边的位数(the leftmost bit number to be moved from the source),编码在“imms”字段中。对于 32 位变体:在 0 到 31 的范围内;对于 64 位变体:范围从 0 到 63。

下面是使用 BFM 指令的例子。

    long long int x = 0x444444;
    long long int y = 0x79;

    asm volatile(
        "BFM %x[x], %x[y], #8, #4\n"
    :[x] "+r"(x),
    [y] "+r"(y)
    :
    : "cc", "memory");

执行 BFM %x[x], %x[y], #8, #4,将 0x79(0b01111001) 中的 0 ~ 4 位(4 + 1 = 5 共 5 位)(0b11001)移动到目标寄存器 %x[x],也就是将 0x19 移动到 %x[x] 的最左边(从 64 - 8 = 56 位开始复制),其它位保持不变,最终为 0x1900 0000 0044 4444。

14. UBFM

UBFM(Unsigned Bitfield Move —— 无符号位域移动)指令通常通过其别名之一进行访问,该别名始终是反汇编的首选。

  • 如果 <imms> 大于或等于 <immr>,则将从源寄存器中的位位置 <immr> 开始的(<imms> - <immr> + 1)位的位域复制到目标寄存器的最低有效位。

  • 如果 <imms> 小于<immr>,则将源寄存器的最低有效位中的(<imms> + 1)位的位域复制到目标寄存器的位位置(regsize - <immr>),其中 regsize 是 32 或 64 位的目标寄存器大小。

在这两种情况下,位域前面和后面的目标位都设置为零。

该指令由别名 LSL(立即数)、LSR(立即数)、UBFIZ、UBFX、UXTB 和 UXTH 使用。

在这里插入图片描述

32-bit (sf == 0 && N == 0)

UBFM <Wd>, <Wn>, #<immr>, #<imms>

64-bit (sf == 1 && N == 1)

UBFM <Xd>, <Xn>, #<immr>, #<imms>

<Wd> 是通用目标寄存器的 32 位名称,在“Rd”字段中编码。

<Wn> 是通用源寄存器的 32 位名称,在“Rn”字段中编码。

<Xd> 是通用目标寄存器的 64 位名称,在“Rd”字段中编码。

<Xn> 是通用源寄存器的 64 位名称,在“Rn”字段中编码。

<immr> 是循环右移量,在“immr”字段中编码。对于 32 位变体:在 0 到 31 的范围内;对于 64 位变体:是在 0 到 63 范围内。

<imms> 是要从源移动的最左边的位数(the leftmost bit number to be moved from the source),编码在“imms”字段中。对于 32 位变体:在 0 到 31 的范围内;对于 64 位变体:范围从 0 到 63。

下面是使用 UBFM 指令的例子。

    long long int x = 0x444444;
    long long int y = 0x79;

    asm volatile(
        "UBFM %x[x], %x[y], #8, #4\n"
    :[x] "+r"(x),
    [y] "+r"(y)
    :
    : "cc", "memory");

执行 UBFM %x[x], %x[y], #8, #4,将 0x79(0b01111001) 中的 0 ~ 4 位(4 + 1 = 5 共 5 位)(0b11001)移动到目标寄存器 %x[x],也就是将 0x19 移动到 %x[x] 的最左边(从 64 - 8 = 56 位开始复制),其它位清零,最终为 0x1900 0000 0000 0000。

15. SBFM

SBFM(Signed Bitfield Move —— 有符号位域移动)指令通常通过其别名之一访问,该别名始终是反汇编的首选。

  • 如果 <imms> 大于或等于 <immr>,则将从源寄存器中的位位置 <immr> 开始的(<imms> - <immr> + 1)位的位域复制到目标寄存器的最低有效位。

  • 如果 <imms> 小于<immr>,则将源寄存器的最低有效位中的(<imms> + 1)位的位域复制到目标寄存器的位位置(regsize - <immr>),其中 regsize 是 32 或 64 位的目标寄存器大小。

在这两种情况下,位域后面的目的位被设置为零,位域前面的位被设置到位域的最高有效位的拷贝。

该指令由别名 ASR(立即数)、SBFIZ、SBFX、SXTB、SXTH 和 SXTW 使用。

在这里插入图片描述

32-bit (sf == 0 && N == 0)

SBFM <Wd>, <Wn>, #<immr>, #<imms>

64-bit (sf == 1 && N == 1)

SBFM <Xd>, <Xn>, #<immr>, #<imms>

<Wd> 是通用目标寄存器的 32 位名称,在“Rd”字段中编码。

<Wn> 是通用源寄存器的 32 位名称,在“Rn”字段中编码。

<Xd> 是通用目标寄存器的 64 位名称,在“Rd”字段中编码。

<Xn> 是通用源寄存器的 64 位名称,在“Rn”字段中编码。

<immr> 是循环右移量,在“immr”字段中编码。对于 32 位变体:在 0 到 31 的范围内;对于 64 位变体:是在 0 到 63 范围内。

<imms> 是要从源移动的最左边的位数(the leftmost bit number to be moved from the source),编码在“imms”字段中。对于 32 位变体:在 0 到 31 的范围内;对于 64 位变体:范围从 0 到 63。

下面是使用 SBFM 指令的例子。

    long long int x = 0x444444;
    long long int y = 0x79;

    asm volatile(
        "SBFM %x[x], %x[y], #8, #4\n"
    :[x] "+r"(x),
    [y] "+r"(y)
    :
    : "cc", "memory");

执行 SBFM %x[x], %x[y], #8, #4,将 0x79(0b01111001) 中的 0 ~ 4 位(4 + 1 = 5 共 5 位)(0b11001)移动到目标寄存器 %x[x],也就是将 0x19 移动到 %x[x] 的最左边(从 64 - 8 = 56 位开始复制),它的后面的位清零,前面的位由于符号位为 1,因此全部复制为 1,最终为 0xF900 0000 0000 0000。

16. CLZ

计算前导零位数:Rd = CLZ(Rn)。

在这里插入图片描述

32-bit (sf = 0)

CLZ <Wd>, <Wn>

64-bit (sf = 1)

CLZ <Xd>, <Xn>

<Wd> 是通用目标寄存器的 32 位名称,在“Rd”字段中编码。

<Wn> 是通用源寄存器的 32 位名称,在“Rn”字段中编码。

<Xd> 是通用目标寄存器的 64 位名称,在“Rd”字段中编码。

<Xn> 是通用源寄存器的 64 位名称,在“Rn”字段中编码。

下面是使用 CLZ 指令的例子。

    long long int x = 0;
    long long int y = 0x79;

    asm volatile(
        "CLZ %x[x], %x[y]\n"
    :[x] "+r"(x),
    [y] "+r"(y)
    :
    : "cc", "memory");

执行 CLZ %x[x], %x[y],计算 %x[y] 前导零的位数,即 0x79(0b01111001)中前导零的位数,也就是 64 - 7 = 57,最终将 57 写入 %x[x]

17. RBIT

RBIT 指令反转所有位(反转位序)。

在这里插入图片描述

32-bit (sf = 0)

RBIT <Wd>, <Wn>

64-bit (sf = 1)

RBIT <Xd>, <Xn>

<Wd> 是通用目标寄存器的 32 位名称,在“Rd”字段中编码。

<Wn> 是通用源寄存器的 32 位名称,在“Rn”字段中编码。

<Xd> 是通用目标寄存器的 64 位名称,在“Rd”字段中编码。

<Xn> 是通用源寄存器的 64 位名称,在“Rn”字段中编码。

下面是使用 RBIT 指令的例子。

    long long int x = 0;
    long long int y = 0x79;

    asm volatile(
        "RBIT %x[x], %x[y]\n"
    :[x] "+r"(x),
    [y] "+r"(y)
    :
    : "cc", "memory");

执行 RBIT %x[x], %x[y],反转 %x[y] 中的所有位(反转位序),即 0x79(0b01111001)反转为 0x9E00 0000 0000 0000,最终将 0x9E00 0000 0000 0000 写入 %x[x]

18. REV

REV 指令反转所有字节。

在这里插入图片描述

32-bit (sf = 0)

REV <Wd>, <Wn>

64-bit (sf = 1)

REV <Xd>, <Xn>

<Wd> 是通用目标寄存器的 32 位名称,在“Rd”字段中编码。

<Wn> 是通用源寄存器的 32 位名称,在“Rn”字段中编码。

<Xd> 是通用目标寄存器的 64 位名称,在“Rd”字段中编码。

<Xn> 是通用源寄存器的 64 位名称,在“Rn”字段中编码。

下面是使用 REV 指令的例子。

    long long int x = 0;
    long long int y = 0x12436579;

    asm volatile(
        "REV %x[x], %x[y]\n"
    :[x] "+r"(x),
    [y] "+r"(y)
    :
    : "cc", "memory");

执行 REV %x[x], %x[y],反转 %x[y] 中的所有字节,即 0x12436579 反转为 0x7965 4312 0000 0000,最终将 0x7965 4312 0000 0000 写入 %x[x]

19. REV16

REV16 指令反转 16 位半字中的字节。

在这里插入图片描述

32-bit (sf = 0)

REV16 <Wd>, <Wn>

64-bit (sf = 1)

REV16 <Xd>, <Xn>

<Wd> 是通用目标寄存器的 32 位名称,在“Rd”字段中编码。

<Wn> 是通用源寄存器的 32 位名称,在“Rn”字段中编码。

<Xd> 是通用目标寄存器的 64 位名称,在“Rd”字段中编码。

<Xn> 是通用源寄存器的 64 位名称,在“Rn”字段中编码。

在这里插入图片描述

下面是使用 REV16 指令的例子。

    long long int x = 0;
    long long int y = 0x12436579;

    asm volatile(
        "REV16 %x[x], %x[y]\n"
    :[x] "+r"(x),
    [y] "+r"(y)
    :
    : "cc", "memory");

执行 REV16 %x[x], %x[y],反转 %x[y] 中 16 位半字中的字节,即 0x12436579 反转为 0x43127965,最终将 0x43127965 写入 %x[x]

20. REV32

REV32 指令反转 32 位字中的字节。

在这里插入图片描述

64-bit

REV32 <Xd>, <Xn>

<Xd> 是通用目标寄存器的 64 位名称,在“Rd”字段中编码。

<Xn> 是通用源寄存器的 64 位名称,在“Rn”字段中编码。

在这里插入图片描述

下面是使用 REV32 指令的例子。

    long long int x = 0;
    long long int y = 0x12436579;

    asm volatile(
        "REV32 %x[x], %x[y]\n"
    :[x] "+r"(x),
    [y] "+r"(y)
    :
    : "cc", "memory");

执行 REV32 %x[x], %x[y],反转 %x[y] 中 32 位字中的字节,即 0x12436579 反转为 0x79654312,最终将 0x79654312 写入 %x[x]

参考资料

1.《ARMv8-A-Programmer-Guide》
2.《Arm® A64 Instruction Set Architecture Armv8, for Armv8-A architecture profile》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/411209.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【失业即将到来?】AI时代会带来失业潮吗?

文章目录前言一、全面拥抱AIGC二、AI正在取代这类行业总结前言 兄弟姐妹们啊&#xff0c;AI时代&#xff0c;说抛弃就抛弃&#xff0c;真的要失业了。 一、全面拥抱AIGC 蓝色光标全面暂停外包&#xff1f; 一份文件截图显示&#xff0c;中国知名4A广告公司&#xff0c;蓝色光…

汇编第二次上机实验(续第一次,字符串比较及双重循环)【嵌入式系统】

汇编第二次上机实验&#xff08;续第一次&#xff0c;字符串比较及双重循环&#xff09;【嵌入式系统】前言推荐说明汇编第二次上机实验&#xff08;续第一次&#xff0c;字符串比较及双重循环&#xff09;内容1 sort说明流程图代码编写结果分析2 string流程图代码编写结果分析…

Nginx的安装、反向代理、负载均衡及部署项目

Nginx 一、Nginx简介 Nginx称为:负载均衡器或 静态资源服务器:html,css,js,img ​ Nginx(发音为“engine X”)是俄罗斯人编写的十分轻量级的HTTP服务器,是一个高性能的HTTP和反向代理服务器&#xff0c;同时也是一个IMAP/POP3/SMTP 代理服务器。Nginx是由俄罗斯人 Igor Syso…

DOM(上)

DOM&#xff08;文档对象模型&#xff09;&#xff1a;处理可扩展标记语言(HTML或XML&#xff09;的标准编程接口&#xff0c;可以改变网页的内容、结构和样式。DOM树&#xff1a; …

大数据项目实战之数据仓库:电商数据仓库系统——第2章 数据仓库建模概述

第2章 数据仓库建模概述 2.1 数据仓库建模的意义 如果把数据看作图书馆里的书&#xff0c;我们希望看到它们在书架上分门别类地放置&#xff1b;如果把数据看作城市的建筑&#xff0c;我们希望城市规划布局合理&#xff1b;如果把数据看作电脑文件和文件夹&#xff0c;我们希…

CMake——从入门到百公里加速6.7s

目录 一、前言 二、HelloWorld 三、CMAKE 界面 3.1 gui正则表达式 3.2 GUI构建 四 关键字 4.1 add_library 4.2 add_subdirectory 4.3 add_executable 4.4 aux_source_directory 4.5 SET设置变量 4.6 INSTALL安装 4.7 ADD_LIBRARY 4.8 SET_TARGET_PROPERTIES 4.9…

[JavaEE]----Spring03

文章目录Spring_day031&#xff0c;AOP简介1.1 什么是AOP?1.2 AOP作用1.3 AOP核心概念2&#xff0c;AOP入门案例2.1 需求分析2.2 思路分析2.3 环境准备2.4 AOP实现步骤步骤1:添加依赖步骤2:定义接口与实现类步骤3:定义通知类和通知步骤4:定义切入点步骤5:制作切面步骤6:将通知…

测试-子查询及数据更新

测试-子查询及数据更新 目录测试-子查询及数据更新1、修改borrow表增加一列&#xff1b;修改日期数据&#xff08;两条语句完成&#xff09;题目代码题解2、 SQL更新&#xff1a;删除-删除“吴宾”的所有成绩记录题目代码3、SQL查询&#xff1a;查询没有被订购的商品题目代码4、…

CMake GUI工具使用 MinGW 64构建工程

系列文章目录 文章目录系列文章目录前言一、open Project是灰色&#xff1f;前言 CMake GUI 打开 CMake GUI。 在 “Where is the source code” 字段中&#xff0c;选择 Krita 源代码目录&#xff1a;E:/krita-dev/krita。 在 “Where to build the binaries” 字段中&#x…

9.Java面向对象----封装

Java面向对象—封装 面向对象简称 OO&#xff08;Object Oriented&#xff09;&#xff0c;20 世纪 80 年代以后&#xff0c;有了面向对象分析&#xff08;OOA&#xff09;、 面向对象设计&#xff08;OOD&#xff09;、面向对象程序设计&#xff08;OOP&#xff09;等新的系统…

Python 小型项目大全 26~30

二十六、斐波那契 原文&#xff1a;http://inventwithpython.com/bigbookpython/project26.html 斐波那契数列是一个著名的数学模式&#xff0c;被认为是 13 世纪意大利数学家斐波那契的杰作&#xff08;尽管其他人发现它的时间更早&#xff09;。序列从 0 和 1 开始&#xff0…

SAR ADC系列16:CDAC上机实践+作业

目录 作业和上机实践&#xff1a; 通过仿真确定桥接电容Ca的尺寸 采样技术和CDAC相结合 电容校正 为什么在100...0和011...1之间最差&#xff1a;电容的瓶颈在MSB上面 为什么INL最差也发生在中间Code 其他问题 频谱混叠 上级板采样网络时序问题 共模相关问题 关于V…

数据库----------约束、主键约束

目录 1.简介 1.概念 2.作用 3.分类 2.主键约束 1.概念 2.操作 1.添加单列主键 2.添加多列联合主键 3. 通过修改表结构添加主键 4.删除主键 1.简介 1.概念 约束英文: constraint 约束实际上就是表中数据的限制条件 2.作用 表在设计的时候加入约束的目的就是为了…

系统无损迁移、硬盘系统复制完整教程(常用于升级更大硬盘的场景)

阿酷TONY / 2023-4-15 / 长沙 这个教程的应用背景或场景是这样的&#xff1a; 原本使用的ThinkPad笔记本电脑是250G的SSD固态硬盘&#xff0c;使用了一两年后&#xff0c;空间不足了&#xff0c;这个时候需要换一块500G或更大的SSD硬盘&#xff0c;那么问题来了&#xff0c;通…

人员跌倒识别检测系统 yolov7

人员跌倒识别检测系统通过PythonYOLO7网络模型算法&#xff0c;人员跌倒识别检测算法模型对现场画面中有人员倒地摔倒行为实时分析预警&#xff0c;发现则立即抓拍存档告警同步提醒后台值班人员及时处理。YOLOv7 的发展方向与当前主流的实时目标检测器不同&#xff0c;研究团队…

(十二)排序算法-插入排序

1 基本介绍 1.1 概述 插入排序属于内部排序法&#xff0c;是对于欲排序的元素以插入的方式找寻该元素的适当位置&#xff0c;以达到排序的目的。 插入排序的工作方式非常像人们排序一手扑克牌一样。开始时&#xff0c;我们的左手为空并且桌子上的牌面朝下。然后&#xff0c;…

Flink处理大型离线任务稳定性与性能调优探索

Apache Flink作为分布式处理引擎&#xff0c;用于对无界和有界数据流进行状态计算。其中实时任务用于处理无界数据流&#xff0c;离线任务用于处理有界数据。通过本文你将掌握让大型离线任务运行稳定的能力&#xff0c;同时能够通过分析离线任务运行特点&#xff0c;降低任务运…

150.网络安全渗透测试—[Cobalt Strike系列]—[DNS Beacon原理/实战测试]

我认为&#xff0c;无论是学习安全还是从事安全的人多多少少都会有些许的情怀和使命感&#xff01;&#xff01;&#xff01; 文章目录一、DNS Beacon原理1、DNS Beacon简介2、DSN Beacon工作原理二、DNS Beacon实战测试1、实战测试前提2、实战测试过程一、DNS Beacon原理 1、…

大数据分析工具Power BI(三):导入数据操作介绍

导入数据操作介绍进入PowBI&#xff0c;弹出的如下页面也可以直接关闭&#xff0c;在Power BI中想要导入数据需要通过Power Query 编辑器&#xff0c;Power Query 主要用来清洗和整理数据。文件资料下载&#xff1a;https://download.csdn.net/download/xiaoweite1/87587711一、…

Wijmo JavaScript UI 5.20222.877 Crack

Wijmo使用更快、更灵活的 JavaScript UI 组件构建更好的应用程序 使用 Wijmo&#xff0c;利用我们引人注目的 UI 组件库&#xff0c;将更多时间花在应用程序的核心功能上。要求零依赖&#xff0c;Wijmo sports弹性网格&#xff0c;业内最好的 JavaScript 数据网格&#xff0c;提…