Linux汇编语言编程-机器语言

机器语言是处理器看到的语言。 在获取-执行周期【fetch-execute cycle 】中获取的字节是机器码的字节。汇编语言可以定义为一种使程序员能够控制机器码的语言。汇编语言指定机器码。如果不熟悉机器语言,汇编语言的这一特性是不明显的。本章介绍 x86 机器码的主要特征。

将汇编代码转换为机器码的过程称为汇编【assembling】。 以汇编语言作为输入,并产生机器语言作为输出的程序称为汇编程序【assembler】。 它类似于编译器,但它在较低级别上运行。

相反,将机器码转换为汇编语言的过程称为反汇编【unassembling】。 执行此操作的程序称为反汇编程序【unassembler】。

Assembling Simple Programs

要讲述 x86 处理器机器码的整个故事,涉及到许多棘手的细节。 然而,在第 4.3 节到第 4.5 节中使用的所有编号的程序中,为 x86 汇编语言的子集指定机器码是很容易的。 表 5.1 给出了这部分 x86 汇编语言的编码【Coding】。 大多数机器码以十六进制给出,但某些字节必须以二进制给出。 字节数从 1 到 6 不等。 例如,表的第一行显示的  MOV reg,reg  的代码是一个双字节代码【two-byte code】,其中第一个以十六进制给出,第二个以二进制给出。 以二进制给出的字节是包含寄存器代码【 register codes 】的字节。 S S S 在二进制编码中表示源寄存器的三位代码。 D D D 表示目标寄存器的三位代码。 寄存器代码【register codes】在下面有给出。 命令中出现的每个“imm” 会指定四个附加字节,这些字节必须由程序员提供。 示例如下。 根据表 5.1,程序 5.1 可以按如下方式进行机器码汇编/机器码组装【machine assembled】:

Table 5.1. Some 32-Bit Machine Coding

First ByteSecond Byte4 More
MOVreg, reg891 1 S S S D D D
MOVreg, imm1 0 1 1 1 D D D___
ADDreg, reg011 1 S S S D D D
ADDreg, imm811 1 0 0 0 D D D[1]___
SUBreg, reg291 1 S S S D D D
SUBreg, imm811 1 1 0 1 D D D[1]___
INCreg0 1 0 0 0 D D D
DECreg0 1 0 0 1 D D D
INEAX, [DX]ED
OUT[DX], EAXEF
RETC3
JMPimmE9___
JZimm0F84___
JNZimm0F85___
JSimm0F88___
JNSimm0F89___

3-Bit Register Codes
EAX000ESP100
ECX001EBP101
EDX010ESI110
EBX011EDI111

Register Codes

第一个命令的第一个字节,即 BA ,使用 MOV reg,imm  给出的 1011 1DDD 代码【code】进行编码【encoded】。 DDD 占位用 EDX 的寄存器代码 010 填充,其结果是二进制代码 1011 1010 或十六进制代码 BA。

第二个 MOV 命令,即 MOV ECX,EAX 被编码为89 C1,它是使用图表中的 MOV reg,reg 进行的编码,其中第二个字节按照规范被指定为 11 SSS DDD。,而EAX 是源寄存器,其代码为 000。ECX 是目标寄存器,其代码为 001,结果第二个字节为 11 000 001,即 C1。

Example 5.1. 

Label  Source Code     Address  Machine Code
       MOV EDX, 0            0  BA 00
                             2  00 00
                             4  00
       IN EAX, [DX]          5  ED
       MOV ECX, EAX          6  89 C1
       IN EAX, [DX]          8  ED
       MOV EDX, EAX          9  89 C2
ORD    SUB EAX, ECX          B  29 C8
       JZ GCD                D  0F 84
                             F  11 00
                            11  00 00
       JNS NXT              13  0F 89
                            15  04 00
                            17  00 00
       MOV EAX, ECX         19  89 C8
       MOV ECX, EDX         1B  89 D1
NXT    MOV EDX, EAX         1D  89 C2
       JMP ORD              1F  E9 E7
                            21  FF FF
                            23  FF
GCD    MOV EAX, EDX         24  89 D0
       MOV EDX, 1           26  BA 01
                            28  00 00
                            2A  00
       OUT [DX], EAX        2B  EF
       RET                  2C  C3

Little Endian Immediate Codes

该程序中的第一个和最后一个 MOV 命令都包含立即值【immediate values】。 它们都将四字节值存储在四字节寄存器中。 请注意,在最后一个 MOV 命令中,四字节立即值 00000001H 存储为 01 00 00 00。

Relative Jumps

在可行的情况下,x86 处理器使用的跳转编码使用相对地址而不是绝对地址。 该程序中的所有跳转指令都将跳转编码【encode】为相对跳转。 绝对跳转【absolute jump】将指定一个实际地址【actual address】作为跳转目标,而相对编码【relative encoding】则指定从下一条指令的开头开始要跳转的字节数。 该值可以被解释为一个有符号的数字,对于向后跳转来说是一个负值。 处理器【processor】将编码值【encoded value】与下一条指令的地址相加,以获得要跳转到的指令的地址。 例如, JMP NXT 指令有一个小端编码 4; 从  MOV EAX, ECX 开始的字节 89 算起 4 个字节,就到了  MOV EDX, EAX 开始的字节 89 。 该命令是 JMP NXT 的目标。  JMP ORD  指令包含相对跳转值 FFFFFFE7H = −25。 从  MOV EAX, EDX 开始的字节 89 开始向后数 25 个字节,得到字节 29 ,即  SUB EAX,ECX 代码的第一个字节。

Short Jumps

尽管值 17、4 和 -25 很容易适合一字节有符号范围,但程序中的相对跳转值均以四个字节进行编码。 有一些替代编码可用于节省单字节跳转的空间。 这些跳跃称为短跳【short jumps】。 例如, JNS NXT  指令的短跳【short jump】编码为 79 04。条件短跳【conditional short jumps】的机器码可以通过去掉字节 OF 并从第二个字节中减去 10H 获得。  JMP  命令的短代码是 EB。 在 Edlinas 中,可以使用 s 键将长跳【long jump】转换为短跳【short jump】。 在 NASM 中,朴素的 JMP  指令总是意味着短跳转【short jump】。 无法以单字节编码的  JMP 指令会收到错误消息。 要指定使用较长编码的跳转,请使用 JMP NEAR 。 在当前上下文中,“远【far】”跳转似乎比“短【near】”跳转更有意义,但远跳实际上指的是使用绝对编码【absolute encoding】的跳转,如第 12 章所示。

由于大多数跳转不超过 128 字节,因此为它们使用特殊编码是有意义的。 8086 的指令集实际上只有条件跳转的简短版本。 标识长跳的码 OF 直到 80386 才出现。

Opcode Space

上一节中给出的机器码可用于汇编【assemble】各种简单的程序。 另一方面,总的来说,它们仅代表完整 x86 指令集的一小部分。 在本节中,概述了整个 x86 机器码集。 表 5.2 显示了机器码的第一个字节传达的信息。

表中的大多数条目都包含助记符【mnemonic】和操作数【operand】信息。 在少数情况下,此信息完整地指定出了两者。 例如,表中字节 EE 对应的条目:

      OUT
    [DX],AL

在其他情况下,明确给出助记符,但使用字母的键【keys】来描述一类【class】允许的操作数。

  • r 代表寄存器
  • m 代表内存【memory】
  • i 代表立即数
  • b 代表字节【byte】
  • 2 代表 2 字节
  • v 表示 32 位或 16 位
  • e在 32 位中表示 E ,在 16 位中消失

Stephen Morse 在其优秀著作 80386/387 Architecture 中使用了这些键【keys】。

考虑表中字节 03 处的条目:

     ADD
    rv,rmv

由于第一个操作数的位置包含 rv,这表明第一个操作数必须是 16 位或 32 位寄存器。 由于第二个操作数位置包含 rmv,因此第二个操作数必须是 16 位或 32 位的寄存器或内存操作数。 由于  EDI  和 EAX 是 32 位寄存器,我们看到 ADD EDI,EAX 是一个可以用第一个字节为 03 的代码【code】进行编码【encoded】的指令示例。另一个例子是 ADD EDI,[1234H] 。 由代码的第一个字节所传达的信息类型可以分为几种情况:

  1. 在少数情况下,这个单字节足以完整地指定一条指令。 例如,F4 指定暂停指令: HLT。

  2. 在许多其他情况下,虽然第一个字节足以确定要执行哪个操作,但它并不指定操作数。 在这些情况下,第二个字节通常足以承载操作数信息。 第二个字节称为 ModRM 字节。 例如,如果第一个字节是 89,则表中对应的条目是  MOV rmv,rv  。 除了指定操作 MOV 之外,rmv、rv 这两个关于操作数的键【keys】还传达有关如何解释 ModRM 字节的信息。

  3. 也有一些情况,第一字节并不完全指定一个操作,而只是一个通用类型的操作,ModRM 字节用于完成操作的指定并携带操作数信息。 例如,如果第一个字节是 C1,则表中对应的条目是 Shift rmv,ib。 在这些情况下,ModRM 字节的完整解释需要移至表 5.3。 Shift 并不是助记符。 它只是表 5.3 的一个指针。 我们在表中通过字母是否全部大写来表明这一点。

  4. 如果第一个字节是 OF,那么就有了很多可能性。 OF 传达的信息参见表 5.4。

  5. 如果第一个字节在 D8-DF 范围内,则该命令是浮点命令。 本文不涉及这些命令。

  6. 还有一些前缀字节【prefix bytes】用于修改后续命令【subsequent commands】。在表 5.2 中,前缀字节(例如 LOCK 前缀 F0)显示为底部看护【bottom-sitters】。

以下各节将一一处理这些不同的情况。

Table 5.2. First Byte of Opcode Space

The ModRM Byte

当第一个字节不能携带操作数信息时,ModRM 字节用于携带操作数信息。 ModRM 字节由三部分组成。

ModRM
76543210
  1. 位 7 和 6 是 Mod 位。 当 Mod 位为 11 时,M 部分的位指定寄存器。 否则,M 部分的位用于内存编码。

  2. 位 5、4 和 3 是 R(或寄存器【register】)位,通常使用斜杠符号 /r 来指定。

  3. 位 2、1 和 0 是 M(或内存【memory】)位,用于指定或帮助指定内存位置(Mod 位为 11 时除外)。

rv,rmv Coding

表 5-1 中字节 03 处的条目为:

     ADD
    rv,rmv

我们可以使用这个条目来组装 ADD EDI,EAX 命令。  ADD EDI,EAX  命令需要 ModRM 字节。 第二个操作数位置中的 m 不仅指定第二个操作数可以是内存操作数【memory operand】,而且还指定它必须被编码在 ModRM 字节的 M 位中。 由于第二个操作数是寄存器 EAX,因此 EAX 的位代码 000 占据 ModRM 字节中的 M 位。 由于我们对 M 部分的位【bits】使用的是寄存器,因此这两个 Mod 位必须为 11。第一个操作数(由 r 所示它必然是寄存器)因此被编码在 ModRM 字节的 R 位中。 EDI 是第一个操作数,其代码为 111。因此 ModRM 字节为:

ModRM
76543210
11111000

1111 1000 = F8H

将 03 与 ModRM 字节组合生成  ADD EDI,EAX 的代码 03 F8。

如果在此代码中我们将两个 Mod 位从 11 更改为 00,我们将会得到  ADD EDI,[EAX] 的代码。 这里 M 位用于实际的内存操作数【memory operand】(译注:EAX 寄存器里的值,存储的是内存地址,[] 在这里是一个解引用,类似于C语言里的 * )。 代码 01 和 10 用于编码立即数位移【immediate displacements】,例如  ADD EDI,[EAX + 5],其中位移【displacement】分别为 ib 或 iv 类型。 因此, ADD EDI,[EAX + 5] 的代码是03 78 05(Mod 位用的是 01)。 ADD EDI,[EAX + 87654321H] 的代码是03 B8 21 43 65 87(Mod 位用的是 10)。但是,如果统一执行此编码,则在编码空间中就没有在第 6 章第 6.2.3 节中将会看到的复杂格式的空间了。为了腾出空间对这些格式进行编码,ESP 寄存器的代码被删除了,以提供转义到编码空间的另一个字节(称为 SIB 字节)中。

rmv.rv Coding

当  rmv 和 rv 键颠倒时,三位代码【three-bit codes】就会发生颠倒。 举个例子,假设我们要汇编指令  MOV EDI, EAX。表中字节 8B 的条目匹配并且可以使用与 ADD EDI, EAX  代码相同的 ModRM 字节进行编码。 但表中的字节 89 的条目也匹配:

     MOV
    rmv,rv

使用该条目,我们注意到第一个操作数可以是寄存器并且被编码在 M 位中。 因此,EDI 代码进入最低有效位。 第二个操作数 EAX 编码在 R 位中。

ModRM
76543210
11000111

1100 0111 = C7H

因此,使用表 5.2 中的字节 89 的条目,我们获得  MOV EDI,EAX 的编码为 89 C7。 

Nonregister R Bits

在某些情况下,第一个字节不足以指定操作,但 ModRM 字节的 R 位用于完成指定。 表 5.3 列出了这些情况。 SUB ECX, 32  就是一个例子。 表 5.2 中字节 83 的条目是:

    Immed
    rmv,ib

由于表 5.3 中标记为“Immed”的行在 /r = /5 下有一个  SUB ,我们了解到指令匹配如下编码:

     SUB
    rmv,ib

可以使用 83 作为第一个字节并使用 101 (即 5,前面讲过,首字节只使用83,不足以完全指定操作,需要 R 位来协助)作为 ModRM 字节的 R 位进行编码。 由于第一个操作数 ECX 不是内存,因此 Mod 位必须为 11,M 位将填充 ECX 的代码 001。 所以所需的 ModRM 字节是:

Table 5.3. Instructions Specified by R Bits

/r/0 000/1 001/2 010/3 011/4 100/5 101/6 110/7 111
ImmedADDORADCSBBANDSUBXORCMP
ShiftROLRORRCLRCRSHLSHRSAR
UnaryTEST iNOTNEGMULIMULDIVIDIV
IncDecINCDEC
IndirINCDECCALL mCALL FAR mJMPJMP FARPUSH

 

ModRM
76543210
11101001
1110 1001 = E9H

ib 代表立即字节。 因此  SUB ECX.32  的代码是 83 E9 20。 

386 Space (OF + …)

在 8086 上,字节 OF 编码为指令 POP CS。 但在后续处理器上,该指令被删除,以使 OF 代码可用于指令集中的显著扩展。 表 5.4 显示了被开辟的空间。 与表 5.2 一样,它显示了由单个字节传达的信息,在本例中为初始 OF 字节后面的字节。 表 5.4 中的一些指令首先出现在 80286、80486 或 Pentium 上,但大多数指令首先出现在 80386 上。80286 的大部分新指令都在表 5.2 中。

  1. 与表 5.2 一样,有时一个条目恰好指定一条指令。 例如,OF CA 是 BSWAP EDX 指令的代码(Byte SWAP EDX 寄存器)。
  2. 有时需要 ModRM 字节来传送操作数信息。 前两个字节为 OF C1 的  XADD 指令就是一个例子。
  3. 有时,ModRM 字节用于指定操作。 例如,如果指令的前两个字节是OF 01,那么我们必须检查 ModRM 字节的 R 位来确定操作。 从表 5.5 中我们可以看出,如果 ModRM 字节中的寄存器位为 011,则该指令将是  LIDT 指令(加载中断描述符表)。


在8086计算机上,用于指令POP CS的字节码。在后续的处理器上,该指令被删除,以使OF代码可用于指令集中的显著扩展。表5.4显示了被打开的空间。与表5.2一样,它显示了单个字节所传递的信息,在本例中是初始OF字节后面的字节。表5.4中的一些指令首先出现在80286、80486或Pentium上,但大多数指令首先出现在80386上。80286的大部分新指令在表5.2中。

与表5.2一样,有时一个表项只指定一条指令。例如,OF CA是指令BSWAP EDX(字节交换EDX寄存器)的代码。

有时需要一个ModRM字节来传递操作数信息。前两个字节是C1的XADD指令就是一个例子。

Table 5.4. 386 Space

Table 5.5. 0F Instructions Specified by R Bits

/r/0 000/1 001/2 010/3 011/4 100/5 101/6 110/7 111
LocalTSLDT rm2STR rm2LLDT rm2LTR rm2VERR rm2VERW rm2
GlobalTSGDT m6SIDT m6LGDT m6LIDT m6SMWS rm2LMSW rm2
BitsBT rmv,ibBTS rmv,ibBTR rmv,ibBTC rmv,ib

注:一些代码引用了MMX指令。 这些指令在 Intel 书籍《MMX 技术完整指南》中进行了讨论。 

我们了解到与表 5.5 匹配的指令包含 80486、Pentium 和 MMX 指令以及 80386 指令。 例如, XADD 和 BSWAP 指令首先出现在 80486 上, CPUID 和 RDTSC 首先出现在 Pentium 上。

32-Bit vs. 16-Bit Code

至此,我们已经讨论了仅涉及 32 位通用寄存器的命令的机器代码。 现在我们准备考虑 16 位通用寄存器的编码。

 MOV ECX,EAX  命令,如第 5.1 节所述,可以编码为 89 C1。 对应的16位命令是 MOV CX,AX。 令人惊讶的是,这个命令的代码也是 89 C1! 80386 设计为对 16 位寄存器使用与 32 位寄存器相同的编码。 显然这有问题。 当处理器【processor】获取字节 89 C1 时,应执行哪条指令,MOV ECX,EAX  还是  MOV CX,AX ? 碰巧的是,这个决定是基于处理器中的单个比特/位。 该位决定代码是否被解释为 32 位代码(在这种情况下 89 C1 表示 MOV ECX,EAX  )或 16 位代码(在这种情况下 89 C1 表示  MOV CX,AX )。

当该位被设置时,并不意味着指令  MOV CX,AX  不可用。 为了对 32 位编码假设错误的事实进行编码,使用了一个单字节前缀: 66。 因此,在 32 位代码中 66 89 C1 是  MOV CX,AX  的代码。同样, MOV ECX,EAX  指令在 16 位代码中可用,它的代码是 66 89 C1, 这个前缀被称为操作数大小前缀【 operand size prefix】。 这意味着操作数大小不是默认大小。

通常,该位在运行 Linux 时设置,并在运行 DOS 时清除。 除非另有特别说明,本书中给出的代码假定处理器的位设置为 32 位默认值。 因此,89 C1 表示  MOV ECX,EAX ,66 89 C1 表示  MOV CX,AX 。 

Table 5.6. 32- vs. 16-Bit Coding Example

32-Bit Code16-Bit Code
MOV ECX, EAX89 C166 89 Cl
MOV CX, AX66 89 C189 C1

现在我们看到代码 89 C1 如何具有两种可能的含义之一,解释其中的 v 就很容易了: 

     MOV
    rmv,rv

 

每个操作数标记中的 v 代表变量,其中变量指的是大小可以是 16 位或 32 位。 类似地,寄存器名称(例如 eAX)中的 e 表示在 32 位编码中预期为 EAX,而在 16 位编码中则预期为 AX。

The 8-Bit Registers

尽管 32 位和 16 位寄存器命令被迫共享操作码,但 8 位寄存器通常具有专用操作码。 例如,操作码 8A 指定八位 MOV 指令。 表 5.2 中 8A 的条目为 :

     MOV
    rb,rmb

 rb 代表寄存器字节【register byte】,并在 ModRM 字节的寄存器位中进行编码。 rmb 代表寄存器或内存字节【 register or memory byte 】,并在 ModRM 字节的内存位中进行编码。 8A C1 是  MOV AL,CL 的代码。 表 5.7 列出了 8 位寄存器代码。 CL 的代码进入 M 位,AL 的代码进入 R 位。

Table 5.7. Codes for 8-Bit Registers

Codes for 8-Bit Registers
AL000AH100
CL001CH101
DL010DH110
BL011BH111
ModRM
76543210
11000001

组合两个字节产生 8A C1。 

Linux .0 Files

包含对  printf() 或 scanf() 等函数调用的 C 程序需要链接到这些函数的编译代码。 该代码存储在  libc.so 等库中。 一旦链接【linking】完成,程序就会变得更长。 为了检查程序的机器代码,在完成链接之前查看代码会更容易,因为代码要少得多。 该代码存储在文件扩展名为 .o 的对象模块【object modules】中。 DOS 中的类似文件是.OBJ 文件。 要指示 gnu C 编译器生成 .o 文件,可以使用 -c 开关。 命令:

    linuxbox$ gcc -c mult.c

该命令生成一个 mult.o 文件。 该文件包含程序的机器代码,以及允许链接器【linker】完成其工作的表【table】。

要检查目标代码文件,可以使用本书附带的 ob 程序(对象转储)或标准 Unix 实用程序 od 程序(八进制转储)。 要使 od 以十六进制显示,请使用开关 -tx 和 -Ax。

    linuxbox$ od -tx -Ax mult.o

如果使用 ob 则不需要开关:

    linuxbox$ ob mult.o

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

一句话木马是什么?代码实例及绕过方法

一句话木马是指一种短小的、通常只有一行代码的恶意软件,它被用来在目标系统中执行攻击者的命令或代码。这种类型的木马通常通过各种途径被注入到目标系统中,一旦成功运行,攻击者就可以远程控制受感染的系统。一句话木马的目的包括窃取敏感信…

RPC(3):HttpClient实现RPC之GET请求

1HttpClient简介 在JDK中java.net包下提供了用户HTTP访问的基本功能,但是它缺少灵活性或许多应用所需要的功能。 HttpClient起初是Apache Jakarta Common 的子项目。用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 H…

关于“Python”的核心知识点整理大全27

目录 10.5 小结 第11 章 测试代码 11.1 测试函数 name_function.py 函数get_formatted_name()将名和姓合并成姓名,在名和姓之间加上一个空格,并将它们的 首字母都大写,再返回结果。为核实get_formatted_name()像期望的那样工…

【超图】SuperMap iClient3D for WebGL/WebGPU ——地形影像

作者:taco 号外!号外!开新坑了!开新坑了!对于一个代码小白来讲,设置可能是刚接触开发的人(还没接触准备接触)的人来说。对于读代码或是在对产品的使用上会存在许许多多的疑惑。接下来…

uniapp笔记

/pages/component/swiper/swiper /pages/component/button/button navigator image 设置界面标题 页面跳转 设置TabBar 发起一个请求 网络请求

计算机组成原理——中央处理器cpu1-20

1、中央处理器(CPU)是指什么。C A、 运算器 B、 控制器 C、 运算器和控制器 D、 运算器、控制器和主存储器 2、在CPU中跟踪指令后继地址的寄存器是什么。B A、 主存地址寄存器 B、 程序计数器 C、 指令寄存器 D、 状态条件寄存器 3、操作控制器的…

VR党建:VR全景技术如何助力党建知识传播

导语: 随着科技的不断发展,虚拟现实技术逐渐深入人们生活的方方面面。VR全景技术作为一种全新的沉浸式体验方式,被广泛应用于娱乐、教育、医疗等领域。而在党建学习中,VR全景技术也展现出了巨大的潜力,成为了一种创新…

项目中webpack优化配置(持续更新)

项目中webpack优化配置 1. 开发效率, 体验 DLL(开发过程中减少构建时间和增加应用程序的性能) 使用 DllPlugin 进行分包,使用 DllReferencePlugin(索引链接) 对 manifest.json 引用,让一些基本不会改动的代码先打包…

java-sec-code中的文件上传

java-sec-code中的文件上传 这里仅讨论文件上传,不讨论后续利用(中间件解析漏洞等不做讨论) 任意文件伤害上传 any-->uploada.html-->upload访问any路由时,会出现upload.html的上传文件界面,指向upload路由 GetMapping("/any&qu…

java SSM教师业绩管理系统myeclipse开发mysql数据库springMVC模式java编程计算机网页设计

一、源码特点 java SSM教师业绩管理系统是一套完善的web设计系统(系统采用SSM框架进行设计开发,springspringMVCmybatis),对理解JSP java编程开发语言有帮助,系统具有完整的源代 码和数据库,系统主要采…

谷歌发布Gemini 1.0,开启生成式AI模型新时代!

🎥 屿小夏 : 个人主页 🔥个人专栏 : IT杂谈 🌄 莫道桑榆晚,为霞尚满天! 文章目录 📑前言一. Gemini的发布前期1.1 Gemini的准备1.2 DeepMnid 二. Gemini的三大杀手锏2.1 多模态能力2…

Linux 音视频SDK开发实践

一、兼容性适配处理 为什么需要兼容处理? 1、c兼容处理 主要有ABI兼容性问题,不同ubuntu系统依赖的ABI版本如下: ubuntu 18.04ubuntu 16.04ubuntu 14.04g7.55.44.8stdc版本libstdc.so.6.0.25libstdc.so.6.0.21libstdc.so.6.0.19GLIBCXXG…

详解YOLOv5网络结构/数据集获取/环境搭建/训练/推理/验证/导出/部署

一、本文介绍 本文给大家带来的教程是利用YOLOv5训练自己的数据集,以及有关YOLOv5的网络结构讲解/数据集获取/环境搭建/训练/推理/验证/导出/部署相关的教程,同时通过示例的方式让大家来了解具体的操作流程,过程中还分享给大家一些好用的资源…

电脑备忘录小工具怎么添加?怎么在电脑桌面添加备忘录?

作为一名天天用电脑办公的上班族,如果你需要对某个项目或问题进入深入思考,想要快速记录想法和思路,这时候会选择什么样的记事方式呢?如果你需要记录常用的工作文字内容、工作注意事项、项目流程、待办的工作安排等,用…

vue 将后端返回的二进制流进行处理并实现下载

什么是二进制流文件? 二进制文件是一种计算机文件格式,它的数据以二进制形式存储,与文本文件不同。二进制文件可以包含任意类型的数据,例如图像、音频、视频、可执行文件、压缩文件等,而文本文件则仅仅包含 ASCII 码或…

PCL 点云匹配 之NICP(Normal ICP)

一、概述 上面一篇中我们已经得出了一个结论,就是ICP虽然简单,但是也有明显的缺点 1、计算速度慢,收敛慢,迭代次数多 2、对内存的开销比较大 3、很容易陷入局部最优的困局 因此我们在经典ICP的基础上添加一两个约束: 第…

鸿蒙开发之简单登录页面

Entry Component struct Index {State loading:booleanfalse;build() {Row() {Column({ space: 5 }) {Image($r("app.media.app_icon")).width(100).height(100).borderRadius(10).margin({top: 60})Text("登录界面").fontSize(40).fontWeight(FontWeight.…

Apollo Planning——PathLaneBorrowDecider

引用 组件数据缓存 DependencyInjector DependencyInjector:依赖注入器,这是一个过于专业的名词,来自软件设计模式的依赖倒置原则的一种具体实现方式,起到模块解耦作用。“依赖倒置原则(Dependence Inversion Principle)是程序要…

全国国控监测点点位数据,shp/excel格式,已可视化

基本信息. 数据名称: 全国国控监测点点位数据 数据格式: shpexcel 时间版本:2023年 数据几何类型: 点 数据精度:全国 数据坐标系: WGS84 数据来源:网络公开数据 数据字段: 序号字段名称字段说明1province省名称2city城市…

设计模式 原型模式 与 Spring 原型模式源码解析(包含Bean的创建过程)

原型模式 原型模式(Prototype模式)是指:用原型实例指定创建对象的种类,并且通过拷贝这些原型,创建新的对象。 原型模式是一种创建型设计模式,允许一个对象再创建另外一个可定制的对象,无需知道如何创建的细节。 工作原…