【ARMv8 编程】A64 流控制指令

news2024/11/24 0:44:26

A64 指令集提供了许多不同种类的分支指令。对于简单的相对分支,即那些从当前地址偏移的分支,使用 B 指令。无条件简单相对分支可以从当前程序计数器位置向后或向前分支最多 128MB。 有条件的简单相对分支,其中条件代码附加到 B,具有 ±1MB 的较小范围。

调用子程序时,需要将返回地址存储在链接寄存器(X30)中,使用 BL 指令。这没有条件版本。BL 的行为类似于 B 指令,具有将返回地址存储在寄存器 X30 中的附加作用,返回地址是 BL 之后指令的地址。

除了这些 PC 相关指令外,A64 指令集还包括两个绝对分支。 BR Xn 指令对 Xn 中的地址执行绝对分支,而 BLR Xn 具有相同的效果,但还将返回地址存储在 X30(链接寄存器)中。 RET 指令的行为类似于 BR Xn,但它向分支预测逻辑提示它是一个函数返回。RET 默认分支到 X30 中的地址,但可以指定其他寄存器。

A64 指令集包括一些特殊的条件分支。在某些情况下,这些允许提高代码密度,因为不需要显式比较。

CBZ Rt, label // 如果为零则比较并分支
CBNZ Rt, label // 如果不为零则比较并分支

这些指令将 32 位或 64 位源寄存器与零进行比较,然后有条件地执行分支。分支偏移量的范围为 ± 1MB。这些指令不读取或写入条件代码标志(NZCV)。

有两个类似的测试和分支指令

TBZ Rt, bit, label // 如果 Rt<bit> 为零,则测试并分支
TBNZ Rt, bit, label // 如果 Rt<bit> 不为零,则测试并分支

这些指令在立即和条件分支指定的位位置测试源寄存器中的位,具体取决于该位是设置还是清除。分支偏移量的范围为 ±32kB。与 CBZ/CBNZ 一样,这些指令不读取或写入条件代码标志(NZCV)。

一、分支指令

1.1 B

分支指令导致无条件分支到 PC 相对偏移处的标签,并提示这不是子例程调用或返回。

在这里插入图片描述

B <label>

<label> 是要无条件跳转到的程序标签。 它与该指令地址的偏移量在 +/-128MB 范围内,编码为“imm26”乘以 4。

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

    long long int x = 0;
    long long int y = 0;
    long long int z = 0;
    LOGD("x=%llx y=%llx z=%llx", x, y, z);
    asm volatile(
        "MOV %x[x], #1\n"
        "B skipy\n"
        "MOV %x[y], #2\n"
        "skipy:\n"
        "MOV %x[z], #3\n"
    :[x] "+r"(x),
     [y] "+r"(y),
     [z] "+r"(z)
    :
    : "cc", "memory");

    LOGD("-----------------------------");
    LOGD("x=%llx y=%llx z=%llx", x, y, z);

由于 B skipy 跳过了 MOV %x[y], #2 这条指令,因此 y 的值还是初始值。

运行结果如下:

2023-05-05 07:59:28.672 12642-12704/com.demo.myapplication D/NativeCore: x=0 y=0 z=0
2023-05-05 07:59:28.672 12642-12704/com.demo.myapplication D/NativeCore: -----------------------------
2023-05-05 07:59:28.672 12642-12704/com.demo.myapplication D/NativeCore: x=1 y=0 z=3

1.2 B.cond

有条件地分支到 PC 相对偏移处的标签,并提示这不是子例程调用或返回。

在这里插入图片描述

B.<cond> <label>

<cond> 是标准条件之一,以标准方式编码在“cond”字段中。

<label> 是有条件跳转到的程序标签。它与该指令地址的偏移量在 +/-1MB 范围内,编码为“imm19”乘以 4。

下面是使用 B.cond 指令的例子。

    long long int x = 0;
    long long int y = 0;
    long long int z = 0;
    LOGD("x=%llx y=%llx z=%llx", x, y, z);
    asm volatile(
        "MOV X0, #2\n"
        "SUBS X0, X0, #1\n"
        "B.EQ skipy\n"
        "MOV %x[x], #1\n"
        "SUBS X0, X0, #1\n"
        "B.EQ skipy\n"
        "MOV %x[y], #2\n"
        "skipy:\n"
        "MOV %x[z], #3\n"
    :[x] "+r"(x),
     [y] "+r"(y),
     [z] "+r"(z)
    :
    : "cc", "memory");

    LOGD("-----------------------------");
    LOGD("x=%llx y=%llx z=%llx", x, y, z);

由于第二条 B.EQ skipy 跳过了 MOV %x[y], #2 这条指令,因此 y 的值还是初始值。第一条 B.EQ skipy 指令因为 第一条 SUBS X0, X0, #1 指令并没有设置 Z 标志位,所以没有跳转,否则 x 的值最终也不会改变。

运行结果如下:

2023-05-05 08:08:27.579 16848-16909/com.demo.myapplication D/NativeCore: x=0 y=0 z=0
2023-05-05 08:08:27.579 16848-16909/com.demo.myapplication D/NativeCore: -----------------------------
2023-05-05 08:08:27.579 16848-16909/com.demo.myapplication D/NativeCore: x=1 y=0 z=3

1.3 BL

BL(Branch with Link)指令分支到 PC 相对偏移,将寄存器 X30 设置为 PC + 4。它提供了这是一个子例程调用的提示。

在这里插入图片描述

BL <label>

<label> 是要无条件跳转到的程序标签。它与该指令地址的偏移量在 +/-128MB 范围内,编码为“imm26”乘以 4。

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

    long long int x = 0;
    long long int y = 0;
    long long int z = 0;
    LOGD("x=%llx y=%llx z=%llx", x, y, z);
    asm volatile(
        "BL mod_y\n"
        "MOV %x[x], #1\n"
        "B mod_z\n"
        "MOV %x[x], #4\n"
        "mod_y:\n"
        "MOV %x[y], #2\n"
        "BR LR\n"
        "mod_z:\n"
        "MOV %x[z], #3\n"
    :[x] "+r"(x),
     [y] "+r"(y),
     [z] "+r"(z)
    :
    : "cc", "memory");

    LOGD("-----------------------------");
    LOGD("x=%llx y=%llx z=%llx", x, y, z);

在这里插入图片描述

运行结果如下:

2023-05-05 09:13:40.038 15433-15580/com.demo.myapplication D/NativeCore: x=0 y=0 z=0
2023-05-05 09:13:40.038 15433-15580/com.demo.myapplication D/NativeCore: -----------------------------
2023-05-05 09:13:40.038 15433-15580/com.demo.myapplication D/NativeCore: x=1 y=2 z=3

1.4 BR

BR (Branch to Register)指令无条件地分支到寄存器中的地址,并提示这不是子程序返回。

在这里插入图片描述

BR <Xn>

<Xn> 是保存要分支到的地址的通用寄存器的 64 位名称,在“Rn”字段中编码。

BR 指令的例子参考 BL 指令的例子即可。

1.5 BLR

BLR(Branch with Link to Register)指令在寄存器中的地址调用子程序,将寄存器 X30 设置为 PC+4。

在这里插入图片描述

BLR <Xn>

<Xn> 是保存要分支到的地址的通用寄存器的 64 位名称,在“Rn”字段中编码。

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

    long long int x = 0;
    long long int y = 0;
    long long int z = 0;
    LOGD("x=%llx y=%llx z=%llx", x, y, z);
    asm volatile(
        "BL mod_y\n"
        "MOV %x[x], #1\n"
        "BR LR\n"
        "MOV %x[x], #4\n"
        "mod_y:\n"
        "MOV %x[y], #2\n"
        "BLR LR\n"
        "MOV %x[y], #5\n"
        "mod_z:\n"
        "MOV %x[z], #3\n"
    :[x] "+r"(x),
     [y] "+r"(y),
     [z] "+r"(z)
    :
    : "cc", "memory");

    LOGD("-----------------------------");
    LOGD("x=%llx y=%llx z=%llx", x, y, z);

在这里插入图片描述

BLR 指令执行会设置 LR 寄存器的值为 PC + 4,BR 指令则只分支!

运行结果如下:

2023-05-07 15:58:22.939 4243-4243/com.example.myapplication D/native-armv8a: x=0 y=0 z=0
2023-05-07 15:58:22.939 4243-4243/com.example.myapplication D/native-armv8a: -----------------------------
2023-05-07 15:58:22.939 4243-4243/com.example.myapplication D/native-armv8a: x=1 y=5 z=3

1.6 RET

无条件地从子程序分支返回到寄存器中的地址,并提示这是子程序返回。

在这里插入图片描述

RET {<Xn>}

<Xn> 是保存要分支到的地址的通用寄存器的 64 位名称,在“Rn”字段中编码。 如果不存在则默认为 X30。

下面是使用 RET 指令的例子。将上面例子中 BR LR 改为 RET,x、y、z 最终的值和上面的例子保持一致。

    long long int x = 0;
    long long int y = 0;
    long long int z = 0;
    LOGD("x=%llx y=%llx z=%llx", x, y, z);
    asm volatile(
        "BL mod_y\n"
        "MOV %x[x], #1\n"
        "RET\n"
        "MOV %x[x], #4\n"
        "mod_y:\n"
        "MOV %x[y], #2\n"
        "BLR LR\n"
        "MOV %x[y], #5\n"
        "mod_z:\n"
        "MOV %x[z], #3\n"
    :[x] "+r"(x),
     [y] "+r"(y),
     [z] "+r"(z)
    :
    : "cc", "memory");

    LOGD("-----------------------------");
    LOGD("x=%llx y=%llx z=%llx", x, y, z);

运行结果如下:

2023-05-07 16:21:41.276 19720-19720/com.example.myapplication D/native-armv8a: x=0 y=0 z=0
2023-05-07 16:21:41.276 19720-19720/com.example.myapplication D/native-armv8a: -----------------------------
2023-05-07 16:21:41.276 19720-19720/com.example.myapplication D/native-armv8a: x=1 y=5 z=3

二、条件分支指令

2.1 CBZ

CBZ(Compare and Branch on Zero)指令将寄存器中的值与零进行比较,如果比较相等,则有条件地分支到 PC 相对偏移量处的标签。它提供了这不是子例程调用或返回的提示。该指令不影响条件标志。

在这里插入图片描述

32-bit (sf == 0)

CBZ <Wt>, <label>

64-bit (sf == 1)

CBZ <Xt>, <label>

<Wt> 是要测试的通用寄存器的 32 位名称,编码在“Rt”字段中。

<Xt> 是要测试的通用寄存器的 64 位名称,编码在“Rt”字段中。

<label> 是有条件跳转到的程序标签。它与该指令地址的偏移量在 +/-1MB 范围内,编码为“imm19”乘以 4。

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

    long long int x = 0;
    long long int y = 0;
    LOGD("x=%llx y=%llx", x, y);
    asm volatile(
        "MOV X0, #1\n"
        "CBZ X0, mod_y\n"
        "MOV %x[x], #1\n"
        "SUB X0, X0, #1\n"
        "CBZ X0, mod_y\n"
        "MOV %x[x], #3\n"
        "mod_y:\n"
        "MOV %x[y], #2\n"
    :[x] "+r"(x),
     [y] "+r"(y)
    :
    : "cc", "memory");

    LOGD("-----------------------------");
    LOGD("x=%llx y=%llx", x, y);

第一次执行 CBZ X0, mod_y ,X0 的值不为 0,因此会继续向下执行到 MOV %x[x], #1,接着 SUB X0, X0, #1 对 X0 寄存器减一操作,X0 的值已经为 0,第二次执行 CBZ X0, mod_y 已经满足分支到 mod_y 标签处,所以直接跳到 mod_y 处执行(跳过了 MOV %x[x], #3)。也就是最终 x 的值为 1,y 的值为 2。

运行结果如下:

2023-05-07 16:29:49.401 22423-22423/com.example.myapplication D/native-armv8a: x=0 y=0
2023-05-07 16:29:49.401 22423-22423/com.example.myapplication D/native-armv8a: -----------------------------
2023-05-07 16:29:49.401 22423-22423/com.example.myapplication D/native-armv8a: x=1 y=2

2.2 CBNZ

CBNZ(Compare and Branch on Nonzero)指令将寄存器中的值与零进行比较,如果比较不相等,则有条件地分支到 PC 相对偏移处的标签。它提供了这不是子例程调用或返回的提示。该指令不影响条件标志。

在这里插入图片描述

32-bit (sf == 0)

CBNZ <Wt>, <label>

64-bit (sf == 1)

CBNZ <Xt>, <label>

<Wt> 是要测试的通用寄存器的 32 位名称,编码在“Rt”字段中。

<Xt> 是要测试的通用寄存器的 64 位名称,编码在“Rt”字段中。

<label> 是有条件跳转到的程序标签。它与该指令地址的偏移量在 +/-1MB 范围内,编码为“imm19”乘以 4。

下面是使用 CBNZ 指令的例子。修改 CBZ 指令例子中的第一条 CBZ 指令为 CBNZ 即可。

    long long int x = 0;
    long long int y = 0;
    LOGD("x=%llx y=%llx", x, y);
    asm volatile(
        "MOV X0, #1\n"
        "CBNZ X0, mod_y\n"
        "MOV %x[x], #1\n"
        "SUB X0, X0, #1\n"
        "CBZ X0, mod_y\n"
        "MOV %x[x], #3\n"
        "mod_y:\n"
        "MOV %x[y], #2\n"
    :[x] "+r"(x),
     [y] "+r"(y)
    :
    : "cc", "memory");

    LOGD("-----------------------------");
    LOGD("x=%llx y=%llx", x, y);

第一次执行 CBNZ X0, mod_y ,X0 的值不为 0,因此直接分支到 mod_y 标签处,所以直接跳到 mod_y 处执行(跳过了 中间的其他指令)。也就是最终 x 的值还为 0,但 y 的值已经被修改为 2。

运行结果如下:

2023-05-07 16:36:26.884 31211-31211/com.example.myapplication D/native-armv8a: x=0 y=0
2023-05-07 16:36:26.884 31211-31211/com.example.myapplication D/native-armv8a: -----------------------------
2023-05-07 16:36:26.884 31211-31211/com.example.myapplication D/native-armv8a: x=0 y=2

2.3 TBZ

TBZ(Test bit and Branch if Zero)指令将测试位的值与零进行比较,如果比较相等,则有条件地分支到 PC 相对偏移处的标签。它提供了这不是子例程调用或返回的提示。该指令不影响条件标志。

在这里插入图片描述

TBZ <R><t>, #<imm>, <label>

<R> 是宽度说明符,在“b5”字段中编码。它可以具有以下值:

Rb5
W0
X1

在汇编程序源代码中,始终允许使用“X”说明符,但仅当位数小于 32 时才允许使用“W”说明符。

<t> 为待测通用寄存器的编号 [0-30] 或名称 ZR(31),编码在“Rt”字段中。

<imm> 为要测试的位数,取值范围为 0~63,编码为“b5:b40”。

<label> 是有条件跳转到的程序标签。它与该指令地址的偏移量在 +/-32KB 范围内,被编码为“imm14”乘以 4。

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

    long long int x = 0;
    long long int y = 0;
    LOGD("x=%llx y=%llx", x, y);
    asm volatile(
        "MOV X0, #0b100\n"
        "TBZ X0, 2, mod_y\n"
        "MOV %x[x], #1\n"
        "TBZ X0, 1, mod_y\n"
        "MOV %x[x], #3\n"
        "mod_y:\n"
        "MOV %x[y], #2\n"
    :[x] "+r"(x),
     [y] "+r"(y)
    :
    : "cc", "memory");

    LOGD("-----------------------------");
    LOGD("x=%llx y=%llx", x, y);

执行 MOV X0, #0b100 后,X0 的值为 0b100(也就是从低到高第三位不为 0,从 0 开始计数的话即位的 index 为 2),TBZ X0, 2, mod_y 测试并比较位 index 为 2 处 X0 对应的位,此位为 1,所以不满足 TBZ 分支到 mod_y 处的情况,这会继续执行 MOV %x[x], #1 ,第二次执行 TBZ 指令 TBZ X0, 1, mod\_y,由于满足分支条件,直接跳到 mod_y 处执行(跳过了 MOV %x[x], #3),最终 x 的值为 1,但 y 的值已经被修改为 2。

运行结果如下:

2023-05-07 17:16:43.303 13323-13323/com.example.myapplication D/native-armv8a: x=0 y=0
2023-05-07 17:16:43.303 13323-13323/com.example.myapplication D/native-armv8a: -----------------------------
2023-05-07 17:16:43.303 13323-13323/com.example.myapplication D/native-armv8a: x=1 y=2

2.4 TBNZ

TBNZ(Test bit and Branch if Nonzero)指令将通用寄存器中的位值与零进行比较,如果比较不相等,则有条件地分支到 PC 相对偏移量处的标签。它提供了这不是子例程调用或返回的提示。该指令不影响条件标志。

在这里插入图片描述

TBNZ <R><t>, #<imm>, <label>

<R> 是宽度说明符,在“b5”字段中编码。它可以具有以下值:

Rb5
W0
X1

在汇编程序源代码中,始终允许使用“X”说明符,但仅当位数小于 32 时才允许使用“W”说明符。

<t> 为待测通用寄存器的编号 [0-30] 或名称 ZR(31),编码在“Rt”字段中。

<imm> 为要测试的位数,取值范围为 0~63,编码为“b5:b40”。

<label> 是有条件跳转到的程序标签。它与该指令地址的偏移量在 +/-32KB 范围内,被编码为“imm14”乘以 4。

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

    long long int x = 0;
    long long int y = 0;
    LOGD("x=%llx y=%llx", x, y);
    asm volatile(
        "MOV X0, #0b100\n"
        "TBNZ X0, 2, mod_y\n"
        "MOV %x[x], #1\n"
        "mod_y:\n"
        "MOV %x[y], #2\n"
    :[x] "+r"(x),
     [y] "+r"(y)
    :
    : "cc", "memory");

    LOGD("-----------------------------");
    LOGD("x=%llx y=%llx", x, y);

执行 MOV X0, #0b100 后,X0 的值为 0b100(也就是从低到高第三位不为 0,从 0 开始计数的话即位的 index 为 2),TBNZ X0, 2, mod_y 测试并比较位 index 为 2 处 X0 对应的位,此位为 1,所以满足 TBNZ 分支到 mod_y 处的情况,这会跳过 MOV %x[x], #1 执行,最终 x 的值还为 0,但 y 的值已经被修改为 2。

运行结果如下:

2023-05-07 17:07:33.926 10241-10241/com.example.myapplication D/native-armv8a: x=0 y=0
2023-05-07 17:07:33.926 10241-10241/com.example.myapplication D/native-armv8a: -----------------------------
2023-05-07 17:07:33.926 10241-10241/com.example.myapplication D/native-armv8a: x=0 y=2

参考资料

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

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

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

相关文章

用Pin对二进制文件自动脱壳

Intel Pin Intel Pin在可执行二进制代码中插入一些探测函数,用于观察、记录、分析宿主代码执行过程中的一些与计算机体系结构相关的特性,如访存指令,寄存器内容,寄存器地址等,通过Pin提供的API可以编写各种分析函数,这样程序运行完以后,统计和分析结果也同时产生,分析…

solidworks2020及麦迪工具箱安装

1、麦迪工具箱安装 1&#xff09;下载 下载链接&#xff1a;www.maidiyun.com/download 下载今日制造 2&#xff09;安装 由于电脑上安装了杀毒软件&#xff0c;会直接删除解压后的安装包&#xff0c;因此需要关闭杀毒软件或者在被删除后进入杀毒软件的隔离区将该文件添加…

网站信息收集

网站信息收集 ip信息收集 域名Whois查询 - 站长之家 Whois查询 http://tool.chinaz.com/ 站长工具 https://dns.aizhan.com/ 爱站网 ping检测 ip反查域 https://x.threatbook.cn/ 微步在线 https://toolbar.netcraft.com/site_report 网站查询 http://tool.chinaz.com/n…

JECloud 运行前端模块所遇到的问题(持续学习汇总)

1.依赖安装问题 官网 JECLoud 前端打包部署 1.1 部署前 注意 可以先下载 jecloud-libs 项目 尝试 部署安装 node版本不能过高&#xff01;选择node v14.17.5 版本 在部署前 如果当前node版本过高可以使用 nvm工具 切换到低版本&#xff0c; 但是需要注意的是 切换版本时 …

判断数组中各个元素是否为实数numpy.isreal()

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 判断数组中各个元素是否为实数 numpy.isreal() 选择题 以下程序的运行结果是? import numpy as np anp.array([11j,2j,3.4,5]) print("【显示】a:");print(a) print("【执行】…

Java+Demo 使用java的URLConnection类下载网络文件和支持断网断点续传的简单应用

记录一下使用java的URLConnection类和File类下载网络文件和支持断网断点续传的简单方式 java URLConnection类的结构 demo代码假设下载python的安装包 https://www.python.org/ftp/python/3.10.8/python-3.10.8-amd64.exeFileDownloadUtilsDemo1.java package boot.example…

【ARMv8 编程】A64 系统控制和其他指令

A64 指令集包含与以下相关的指令&#xff1a; 异常处理。系统寄存器访问。调试。提示指令&#xff0c;在许多系统中都有电源管理应用程序。 一、异常处理指令 存在三个异常处理指令&#xff0c;其目的是引发异常。这些用于调用在操作系统&#xff08;EL1&#xff09;、Hyper…

004、PG实例结构

实例结构 1、PostgreSQL实例2、建立一个连接和创建一个会话3、初始化参数文件4、postgresql.conf参数文件5、postgresql.auto.conf参数文件6、参数生效条件7、Memory Architecture8、Process Architecture9、Postgres Server Process10、Backend Processes11、Background Proce…

Linux:split命令、paste命令、ecal命令和正则表达式

Linux&#xff1a;split命令、paste命令、ecal命令和正则表达式 一、split命令二、paste命令三、eval命令四、正则表达式五、实验与应用 一、split命令 split命令—Linux下将一个大的文件拆分成若干小文件语法格式 split 选项 参数 原始文件 拆分后文件名前缀常用选项 选项说…

Claude不能用了?我来帮你

前几天&#xff0c;我在《不需要等待列表&#xff0c;也不用魔法上网的Claude&#xff0c;能否比肩ChatGPT&#xff1f;》一文中&#xff0c;介绍了ChatGPT的同门师兄Claude的注册使用教程。许多同学按照我的教程&#xff0c;很快就无痛使用上了类似ChatGPT的服务。 403 Forbid…

WGCNA | 不止一个组的WGCNA怎么分析嘞!?~(二)(共识网络分析-第二步-构建网络与模块-分步法)

1写在前面 不知道各位最近过得怎么样&#xff0c;昨天去修了脚&#x1f9b6;&#xff0c;感觉自己马上就要迈入油腻中年人的行列了。&#x1f972; 不过说实话&#xff0c;还是挺舒服的&#xff0c;值得再去一次。&#x1f605; 接着更一下WGCNA的教程吧&#xff0c;还是值得大…

TypeScript-基础类型

目录 介绍 布尔值 数字 字符串 数组 元组 Tuple 枚举 Unknown Any Void Null 和 Undefined Never Object 类型断言 关于 Number, String, Boolean, Symbol 和 Object 介绍 在TypeScript中&#xff0c;我们能够处理一些数据单元&#xff0c;例如&#xff1a;数字…

【JavaWeb】-- HTML、CSS、JavaScript

文章目录 HTML1.基本介绍2.快速入门3.基础标签3.1 标题标签3.2 hr标签3.3 字体标签3.4 加粗、斜体、下划线标签3.5 居中标签 4.图片、音频、视频标签5.超链接标签6.列表标签7.表格标签8.布局标签9.表单标签9.1 表单标签概述9.2 form标签属性9.3 代码演示 10.表单项标签 CSS1.概…

【Prompting】ChatGPT Prompt Engineering开发指南(5)

ChatGPT Prompt Engineering开发指南&#xff1a;Transforming 翻译通用翻译器音调转换格式转换拼写检查/语法检查内容来源 在本教程中&#xff0c;我们将探讨如何使用大型语言模型来进行文本转换任务&#xff0c;例如语言翻译&#xff0c;拼写和语法检查&#xff0c;音调调整和…

怎么画邻接表?不用邻接矩阵也能画?

目录 一、有向图的邻接表 二、无向图的邻接表 一、有向图的邻接表 最简单粗暴的方式就是把某个顶点发出的箭头指向的顶点全作为单个结点连接到此顶点的后面。结点数等于边数。 按正常思路的话&#xff0c;是一种递归遍历。 1.选一个点作为出发点。比如选一个v0。 2.从第一出…

Kali-linux控制Meterpreter

Meterpreter是Metasploit框架中的一个杀手锏&#xff0c;通常作为利用漏洞后的攻击载荷所使用&#xff0c;攻击载荷在触发漏洞后能够返回给用户一个控制通道。当使用Armitage、MSFCLI或MSFCONSOLE获取到目标系统上的一个Meterpreter连接时&#xff0c;用户必须使用Meterpreter传…

【C++】leetcode力扣 剑指 Offer 题解

文章预览&#xff1a; 剑指 Offer 03. 数组中重复的数字剑指 Offer 04. 二维数组中的查找剑指 Offer 05. 替换空格剑指 Offer 06. 从尾到头打印链表剑指 Offer 07. 重建二叉树剑指 Offer 09. 用两个栈实现队列剑指 Offer 10- I. 斐波那契数列剑指 Offer 10- II. 青蛙跳台阶问题…

大模型训练数据多样性的重要性

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…

图形编程周刊(2023.001)

图形编程周刊(2023.001) key: webgpu webgl 3d webgis three.js cesium.js 这里是力博荣(Libaro)三维可视化带来的 图形编程周刊, 争取每周五发布。 更新源位置: https://gitee.com/lianming/graphics-programming-weekly/blob/master/2023001/2023001.md 发现的代码 1、th…

少儿编程 中国电子学会图形化编程等级考试Scratch编程三级真题解析(判断题)2023年3月

2023年3月scratch编程等级考试三级真题 判断题(共10题,每题2分,共20分) 26、单击如图所示积木,将生成一个介于1.5和2.5之间的一位小数 答案:错 考点分析:考查随机数积木的使用,随机生成小数的时候,生成的小数位不止一位,所以错误 27、为新建变量命名时,不区分大小…