ARM汇编 : 汇编指令,伪指令,汇编程序格式

news2024/10/6 1:34:27

ARM汇编指令

    • ARM指令集特点
    • ARM工作模式
    • ARM寄存器
      • ARM32
      • ARM64
    • ARM64汇编指令
      • 内存存储访问指令
        • LDR /STR 指令
        • LDP/STP指令(LDR 的变种指令,能够同时操做两个寄存器)
        • LDRB /SDRB 指令(只操作一个字节)
        • LDRH /STRH 指令(只操作两个字节)
        • LDUR/STUR指令 (u和负地址运算相关)
      • 寄存器数据处理指令
        • MOV指令(不用于内存地址)
        • ADD指令 (加)
        • SUB指令 (减) CMP指令只影响cpsr
        • MUL指令 (乘)
        • SDIV指令 (除,无符号除是udiv)
        • AND指令 (位与)
        • ORR指令 (位或)
        • EOR指令 (位异或)
      • 跳转指令
        • B指令 (无条件跳转,遇到ret返回上一层函数)
        • BL指令 (无条件跳转,遇到ret返回该指令的下一条指令)
        • CBNZ/CBZ指令 (和⾮ 0 ⽐较)
        • BLR 指令 (跳转到某寄存器 (的值)指向的地址)
        • RET指令 (函数返回)
    • ARM寻址方式
    • ARM汇编程序格式
      • 标号
      • ARM伪指令/伪操作
        • 全局变量的 定义/初始化
        • ADR、ADRL、LDR 将PC偏移地址值或寄存器偏移地址值传送到寄存器中。
        • LDR 大范围地址读取伪指令(并不是ARM指令中的LDR指令)
          • ADR 小范围地址读取伪指令
          • ADRL 中等范围地址读取伪指令
        • NOP
        • DC系列

ARM指令集特点

计算机的指令集一般可分为4种:
复杂指令集(CISC)
精简指令集(RISC)
显式并行指令集(EPIC)
超长指令字指令集(VLIW)

ARM指令集属于RISC,RISC相对于CISC指令集,主要有以下特点:
●Load/Store架构,CPU不能直接处理内存中的数据,要先将内存中的数据Load(加载)到寄存器中才能操作,然后将处理结果Store(存储)到内存中。
● 固定的指令长度、单周期指令。
● 倾向于使用更多的寄存器来存储数据,而不是使用内存中的堆栈,效率更高。

和原汁原味的RISC相比,ARM也存在一些差异:
● ARM有桶型移位寄存器,单周期内可以完成数据的各种移位操作。
● 并不是所有的ARM指令都是单周期的。
● ARM有16位的Thumb指令集,是32位ARM指令集的压缩形式,提高了代码密度。
● 条件执行:通过指令组合,减少了分支指令数目,提高了代码密度。
● 增加了DSP、SIMD/NEON等指令。

ARM工作模式

ARM处理器有多种工作模式
应用程序正常运行时,ARM处理器工作在用户模式(User mode),用户模式属于普通模式,没有权限对内存和底层硬件进行操作,应用程序如果要读写磁盘上的音频数据,驱动声卡播放音乐,往屏幕写数据显示歌词,则要首先通过系统调用或软中断进入处理器特权模式,运行操作系统内核或硬件驱动代码,才能对底层的硬件设备进行读写操作。
当程序运行出错或有中断发生时,ARM处理器就会切换到对应的特权工作模式。有些特权指令是运行不了的,需要切换到特权模式下才能运行。在ARM处理器中,除了用户模式是普通模式,剩下的几种工作模式都属于特权模式。
ARM工作模式

ARM寄存器

ARM32

ARM32架构寄存器
ARM32 处理器共有37个寄存器,所有这些寄存器都是32位的。
31 个通用寄存器,包括一个程序计数器寄存器
6 个状态寄存器
所有的寄存器编排有重叠的分组,有当前的处理器模式决定使用哪一个分组。在任何时候,15个通用寄存器
(R0 ~ R14),一个或两个状态寄存器和程序计数器是可见的。如下表所示,每一列显示在指定处理器模式下的那些通用寄存器和状态寄存器是可见的。
通用寄存器:通用寄存器(R0 ~ R15)可以分为3组
1,未分组的寄存器R0 ~ R7
2,分组的寄存器R8 ~ R14
3,程序计数器寄存器 PC

未分组的寄存器R0 ~ R7
寄存器R0 ~ R7是未分组的寄存器。它们中的每一个在所有的处理器模式下都是相同的32位物理寄存器。它
们是完全的通用寄存器,没有被处理器架构定义的特殊用途。

分组的寄存器R8 ~ R14
分组的寄存器R8 ~ R14,它们中的每一个代表的物理寄存器依赖与当前的处理器模式。当使用一个通用寄存
器时,几乎所有的指令都可以使用这些分组寄存器。
寄存器R8 ~ R12中的每一个都有两个分组物理寄存器:一组用于FIQ模式,另一组用于其他处理器模式。第
一组可以用R8_fiq ~ R14_fiq表示,另一组用R8_usr ~ R14_usr表示。
寄存器R8 ~ R12在体系中没有任何指定的特殊目的。然而,在简单的中断处理中只需要使用寄存器R8 ~
R14,FIQ模式下的寄存器允许更快的中断处理。
寄存器R3和R14都有6个分组物理寄存器,其中一个用在User和SYSTEM模式下,其余的5个用在5种异常模式下,当需要区分时用如下格式命名:
R13_
R14_
注: 是指usr, svc, abt, und, irq和fiq

寄存器R13通常被用作栈寄指针SP,每一种异常模式都有自己的分组寄存器R13

寄存器R14(链接寄存器或LR)在体系结构中有两种特殊用途:
1,在各种模式下,R14用来保存子程序的返回地址。当一条BL或者BLX指令执行子程序调用时,R14设为子
程序的返回地址。通过复制R14中的地址值到PC中来实现子程序的返回。
2,当发生异常时,相关异常模式下的R14就设为异常返回地址。异常的返回地址与子程序的返回类似,使用
指令恢复异常发生前的程序状态。

寄存器R15:程序计数器
R15是程序计数器(PC),其内容是处理器要取的下一条指令的地址。在ARM状态下,所有的ARM指令都是4字
节长,一直都是字对齐的,这意味着PC的最低两位一直是0,因此PC只包含30位可变的位。ARM体系中的
一些版本也支持其他两种处理器状态。T变种支持Thumb状态,J变种支持Jazelle状态。这些状态下PC可以
是半字和字节对齐。

ARM64

ARM64架构寄存器
通用寄存器:
x0~x7:传递子程序的参数和返回值,使用时不需要保存,多余的参数用堆栈传递,64位的返回结果保存在x0中。
x8:用于保存子程序的返回地址,使用时不需要保存。
x9~x15:临时寄存器,也叫可变寄存器,子程序使用时不需要保存。
x16~x17:子程序内部调用寄存器(IPx),使用时不需要保存,尽量不要使用。
x18:平台寄存器,它的使用与平台相关,尽量不要使用。
x19~x28:临时寄存器,子程序使用时必须保存。
x29:帧指针寄存器(FP),用于连接栈帧,使用时必须保存。
x30:链接寄存器(LR),用于保存子程序的返回地址。
x31:堆栈指针寄存器(SP),用于指向每个函数的栈顶。

特殊寄存器
sp寄存器:Stack Pointer,保存栈顶地址
fp寄存器:Frame Pointer,保存栈底地址
lr寄存器:Link Register,保存跳转指令下一条指令的地址(eg:bl跳转进入执行函数,lr则会保存函数调用完成后需要执行的指令地址)
pc寄存器: 保存当前执行中的指令的下一条指令的地址
cpsr寄存器(状态寄存器):其他寄存器都是存储数据,是个统一的整体;状态寄存器有点特殊,它的每一位都有特殊的含义,记录特定的信息。
CPSR寄存器
最常见的是NZCV标志位,分别代表运算过程中产生的不同状态,可以决定运算结果或者代码执行逻辑。
N:Negative Cndition Flag,代表运算结果是负数
Z:Zero Condition Flag, Z 为 1 代表0,否则Z 为 0 代表 1
C:Carry Condition Flag, 无符号运算有溢出时C 为 1
V:Overflow Condition Flag, 有符号运算有溢出时C 为 1

ARM64汇编指令

一个完整的ARM指令通常由操作码+操作数组成,指令的编码格式如下。

<opcode> {<cond> {s} ,<Rd>,<Rn> {,<operand2>}}

● 使用<>标起来的是必选项,使用{}标起来的是可选项。
● 是二进制机器指令的操作码助记符,如MOV、ADD这些汇编指令都是操作码的指令助记符。
● cond:执行条件,ARM为减少分支跳转指令个数,允许类似BEQ、BNE等形式的组合指令。
● S:是否影响CPSR寄存器中的标志位,如SUBS指令会影响CPSR寄存器中的N、Z、C、V标志位,而SUB指令不会。
● Rd:目标寄存器。
● Rn:第一个操作数的寄存器。
● operand2:第二个可选操作数,灵活使用第二个操作数可以提高代码效率

内存存储访问指令

ARM指令集属于RISC指令集,RISC处理器采用典型的加载/存储体系结构,CPU无法对内存里的数据直接操作,只能通过Load/Store指令来实现:当我们需要对内存中的数据进行操作时,要首先将这个数据从内存加载到寄存器,然后在寄存器中对数据进行处理,最后将结果重新存储到内存中。
ARM64取消32位的LDM, STM, PUSH, POP指令. 与之替代的是 ldr/ ldp, str/ stp

LDR /STR 指令

LDR    x8, [sp]        // 将存储地址为sp的数据读取到x8寄存器中
LDR    x9, [sp, #0x8]  // 将存储地址为sp+0x8的数据读取到x9寄存器中
STR    x0, [sp]         // 将x0寄存器中的值存储到sp的存储地址
STR    x0, [sp, #0x10]  // 将x0寄存器中的值存储到sp+0x10的存储地址

LDP/STP指令(LDR 的变种指令,能够同时操做两个寄存器)

LDP x29, x30, [sp, #0x10]  // 将sp+0x10的值取出来,存⼊寄存器 x29 和寄存器 x30
STPx29, x30, [sp, #0x10]  // 将 x29, x30 的值存⼊sp+0x10存储地址

LDRB /SDRB 指令(只操作一个字节)

LDRB w8, [sp, #0x8] // 将存储器地址为sp+0x8的1个字节数据读⼊寄存器w8,并将w8的⾼24位清零。
SDRB x0, [sp, #0x10]  // 将x0寄存器中的低8位的字节的数据存储到sp+0x10的存储地址

LDRH /STRH 指令(只操作两个字节)

LDRH   w8, [sp, #0x8] // 将存储器地址为sp+0x8的2个字节数据读⼊寄存器w8,并将w8的⾼16位清零。
STRH x0, [sp, #0x10]  // 将x0寄存器中的低16位的字节的数据存储到sp+0x10的存储地址

LDUR/STUR指令 (u和负地址运算相关)

LDUR  w0, [x29, #-0x8]  // 将存储地址为x29-0x8的数据读取到w0寄存器中
STUR  w0, [x29, #-0x8]  // 将x0寄存器中的数据存储到x29-0x8的存储地址

寄存器数据处理指令

MOV指令(不用于内存地址)

MOV    w8, #0x1   //将立即数赋值给w8寄存器
MOV    x0, x8     //将给x0寄存器赋值给给x8寄存器

ADD指令 (加)

ADD    sp, sp, #0x20      // 将寄存器sp的值和立即数0x20相加后保存在寄存器sp中
ADD    x0, x1, x2         // 将寄存器 x1 和 x2 的值相加后保存到寄存器 x0 中
ADD    x0, x1, [x2]       // 将寄存器x1的值加上寄存器x2 的值做为地址,再取该内存地址的内容放⼊寄存器x0中

SUB指令 (减) CMP指令只影响cpsr

SUB    sp, sp, #0x20     // 将寄存器sp的值和立即数0x20相减后保存在寄存器sp中
SUB    x0, x1, x2        // 将寄存器 x1 和 x2 的值相减后保存到寄存器 x0 中

MUL指令 (乘)

MUL    x0, x1, x2     // 将寄存器 x1 和 x2 的值相乘后结果保存到寄存器 x0 中

SDIV指令 (除,无符号除是udiv)

SDIV    x0, x1, x2     //  将寄存器 x1 和 x2 的值相除后结果保存到寄存器 x0 中

AND指令 (位与)

AND    x0, x1, x2     //  将寄存器 x1 和 x2 的值按位与后保存到寄存器 x0 中

ORR指令 (位或)

ORR    x0, x1, x2     //  将寄存器 x1 和 x2 的值按位或后保存到寄存器 x0 中

EOR指令 (位异或)

EOR    x0, x1, x2     //  将寄存器 x1 和 x2 的值按位异或后保存到寄存器 x0 中

跳转指令

B指令 (无条件跳转,遇到ret返回上一层函数)

B指令可以接上后缀,用来和cmp比较后待条件的跳转
状态寄存器

B      0x100002fd0
CMP             W8, #2
B.NE            0x100002fd8

BL指令 (无条件跳转,遇到ret返回该指令的下一条指令)

BL     0x100002f54

CBNZ/CBZ指令 (和⾮ 0 ⽐较)

CBNZ   x0, 0x100002f70    // 如果非0,跳转到0x100002f70指令执行
CBZ   x0, 0x100002f70    // 如果为0,跳转到0x100002f70指令执行

BLR 指令 (跳转到某寄存器 (的值)指向的地址)

BLR     x10

RET指令 (函数返回)

RET

ARM寻址方式

寄存器寻址:通过寄存器名就可以直接对寄存器中的数据进行读写
MOV R1, R2
ADD R1, R2, R3
立即数寻址:立即数以#为前缀,0x前缀表示该立即数为十六进制,不加前缀默认是十进制
MOV R1, #0x3F
ADD R1, R2, #16, 20 ;R1 = R1 + (16循环右移20位)
寄存器偏移寻址:通过第二个操作数operand2的灵活配置(左移或右移操作)作为新的操作数使用
MOV R2, R1, LSL, #3 ;R2 = R1 << 3
ADD R1, R2, #16, 20 ;R1 = R1 + (16循环右移20位)
寄存器间接寻址:寄存器中保存的是数据在内存中的存储地址
LDR R1, [R2]
基址寻址:将寄存器中的地址与一个偏移量相加,生成一个新地址
LDR R1, [FP, #2] ;将FP中的值加2作为新地址,取新地址的内存中的数据放入R1
LDR R1, [FP, #2]! ;将FP=FP+2,再取地址FP的内存中的数据放入R1
LDR R1, [FP, R0] ;将FP中的值加R0作为新地址,取新地址的内存中的数据放入R1
LDR R1, [FP], #2 ;取地址FP的内存中的数据放入R1,再FP=FP+2
STR R1, [FP, #-2] ;将FP=FP-2,再将R1写入地址FP的内存中
STR R1, [FP], #-2 ;将FP=FP-2将R1写入地址FP的内存中,再将FP=FP-2
多寄存器寻址:STM/LDM指令就属于多寄存器寻址,一次可以传输多个寄存器的值。
相对寻址:基址寻址的一种特殊情况。以PC指针作为基地址进行寻址的,以指令中的地址差作为偏移,两者相加后得到的就是一个新地址。
B LOOP

LOOP MOV R0,#3
等价于
ADD PC, PC, #3

ARM汇编程序格式

ARM汇编程序是以段(section)为单位进行组织的。在一个汇编文件中,可以有不同的section,分为代码段、数据段等,各个段之间相互独立,一个ARM汇编程序至少要有一个代码段。我们可以使用AREA伪操作来标识一个段的起始、段名和段的读写属性。
AREA EXAMPLE,CODE,READONLY ;EXAMPLE为段名,段属性CODE/DATA,读写权限READONLY /READWRITE
ENTRY ;汇编程序的运行入口 ;后面表示注释
START
LDR R0,=SRC
LDR R1,=DST
MOV R2, #10
0
LDR R3, [R0], #4
STR R3, [R1], #4
SUBS R2, R2, #1
BNE %B0 ;跳到前面的局部标号0处,构成循环程序结构
AREA EXAMPLEDATA,DATA,READWRITE
SRC DCD 1,2,3,4,5,6,7,8,9,0
DST DCD 0,0,0,0,0,0,0,0,0,0
END ; 汇编程序的结束

标号

在ARM汇编程序中,我们可以使用符号来标识一个地址、变量或数字常量。当用符号来标识一个地址时,这个符号通常又被称为标号。
符号的命名规则和C语言的标识符命名规则一样:由字母、数字和下画线组成,符号的开头不能使用数字,但标号除外。标号比较任性,标号的开头不仅可以是数字,甚至整个标号可以是一个纯数字。符号的命名在其作用域内必须唯一,不能与系统内部或系统预定义的符号同名,不能与指令助记符、伪指令同名。一般情况下,一个符号的作用域是整个汇编源文件。有时候我们会直接通过数字[0,99]而不是使用字符来进行地址引用,我们称这种数字为局部标号。局部标号的作用域为当前段,在汇编程序中,我们可以使用下面的格式来引用局部标号。
%{F|B|A|T} Name{routename} ;{}括起来的部分是可选项
%:引用符号,对一个局部标号产生引用。
F:指示编译器只向前搜索。
B:指示编译器只向后搜索。 ;默认先向后搜索,然后向前搜索
A:指示编译器搜索宏的所有宏命令层。
T:指示编译器搜索宏的当前层。 ;默认搜索从当前层到最顶层的所有宏命令,但不搜索较低层的宏命令
Name:局部标号的名字。
routename:局部标号作用范围名称,使用ROUT定义。 ;对一个标签的引用中指定了routename,则汇编程序将其与最近的一个前ROUT指令的名称进行比较,如果不匹配,则汇编失败

ARM伪指令/伪操作

在汇编语言中,为了编程方便,汇编器也定义了一些特殊的指令助记符,以方便对汇编程序做各种处理。如使用AREA来定义一个段(section),使用GBLA来定义一个数据,使用ENTRY来指定汇编程序的执行入口等,这些指令助记符统称为伪指令或伪操作。
伪操作一般用在符号定义、数据定义、汇编程序结构控制等场合
伪操作
有了这些伪操作辅助,我们就可以设计出更加灵活、功能更加复杂的程序结构,也可以定义一个个汇编子程序,然后在主程序中分别去调用它们,实现汇编语言的模块化编程。

ARM 伪指令不是ARM 指令集中的指令,只是为了方便编程各编译器厂商定义的辅助指令,使用时可以像其他ARM 指令一样使用,在编译时这些指令将被等效的ARM指令代替,有点类似C语言中的预处理命令

全局变量的 定义/初始化

定义一个全局变量并进行初始化。

 GBLA NUM    ;定义一个全局的数值变量,变量名为NUM
 GBLL LOGIC  ;定义一个全局的逻辑变量,变量名为LOGIC  
 GBLS STRING ;定义一个全局的字符串变量,变量名为STRING 

NUM    SETA 4                ;将数值变量NUM赋值为4
LOGIC  SETL {TRUE}           ;将逻辑变量LOGIC赋值为真(不可改为1)
STRING SETS "nhfgtnhgfdb"    ;将字符串变量STRING赋值为相应字符串

与全局变量定义中的三条指令类似,LCLA、LCLL和LCLS分别用于定义局部的数值变量、逻辑变量及字符串变量

ADR、ADRL、LDR 将PC偏移地址值或寄存器偏移地址值传送到寄存器中。

在寄存器之间传递数据可以使用MOV指令,但是当传递的一个内存地址是32位的立即数时,MOV指令就应付不了了
这得从ARM指令的编码格式说起。RISC指令的特点是单周期指令,指令的长度一般都是固定的。在一个32位的系统中,一条指令通常是32位的,指令中包括操作码和操作数,指令中的操作码和操作数共享32位的存储空间:一般前面的操作码要占据几个比特位,剩下来的留给操作数的编码空间就小于32位了。当编译器遇到MOV R0,#0x30008000这条指令时,因为后面的操作数是32位,编译器就无法对这条指令进行编码了。
为了解决这个难题,编译器提供了一个LDR伪指令来完成上面的功能.

LDR 大范围地址读取伪指令(并不是ARM指令中的LDR指令)

MOV R0, #0x30008000 ; 指令执行异常
LDR R0, =0x30008000
为了与ARM指令集中的加载指令LDR区别开来,LDR伪指令中的操作数前一般会有一个等于号=,用来表示该指令是个伪指令。通过LDR伪指令,编译器就解决了向一个寄存器传送32位的立即数时指令无法编码的难题。
当LDR伪指令中的操作数小于8位时,LDR伪指令一般会被MOV指令替代。当LDR伪指令中的操作数大于8位时,LDR伪指令会被编译器转换为LDR标准指令+文字池的形式。
LDR R0, =0x30008000
转为

LDR R0, [PC, #OFFSET]
...
...
DCD 0x30008000

当LDR伪指令中的操作数为一个32位的立即数时,编译器会首先在内存中分配一个4字节大小的存储单元,然后将这个32位的地址0x30008000存放到该存储单元中,该存储单元通常也叫作文字池(literal pool)。接着编译器计算出该存储单元到LDR伪指令之间的偏移OFFSET,然后使用寄存器相对寻址,就可以将这个32位的立即数送到R0寄存器中。偏移量OFFSET的大小一般要小于4KB,所以在分析汇编代码时你会看到,存放这些32位地址常量的文字池一般紧挨着当前指令的代码段,直接放置在当前代码段的后面。

ADR 小范围地址读取伪指令

ADR为小范围的地址读取伪指令,底层使用相对寻址来实现,因此可以做到代码与位置无关

ADR R0, LOOP
...
...
LOOP
    b LOOP
……
ADR R0,ADDR_TAB ;将ADDR_TAB表地址(数组地址)传递给R0;
LDRB R1,[R0,R2] ;使用R2作为参数进行查表
……
ADDR_TAB DCB 0xA0 ,0xF8,0x80,0x48,0xE0,0x4F,0xA3,0xD2

ADR伪指令的作用是将标号LOOP表征的内存地址送到寄存器R0中。编译器在编译ADR伪指令时,会首先计算出当前正在执行的ADR伪指令地址与标号LOOP之间的地址偏移OFFSET,然后使用ARM指令集中的一条标准指令代替之,如使用ADD指令将标号表征的地址送到寄存器R0中。
OFFSET = LOOP-(PC-8)
ADD R0, PC, #OFFSET

LDR伪指令通常被翻译为ARM指令集中的LDR或MOV指令,而ADR伪指令则通常会被ADD或SUB指令代替。在用途上,LDR伪指令主要用来操作外部设备的寄存器,而ADR伪指令主要用来通过相对寻址,生成与位置无关的代码。在一个程序中,只要各个标号之间的相对位置不变,使用ADR伪指令就可以做到与位置无关,将指令代码加载到内存中的任何位置都可以正常运行。在寻址方式上,LDR使用绝对地址,而ADR则使用相对地址,LDR和ADR伪指令的地址适用范围也不同,LDR伪指令适用的地址范围为[0,32GB],而ADR伪指令则要求当前指令和标号必须在同一个段中,地址偏移范围也较小,地址对齐时偏移范围为[0,1020],地址未对齐时偏移范围为[0,4096]。

ADRL 中等范围地址读取伪指令

NOP

NOP 空操作伪指令, 可用于延时,NOP伪指令在编译时将会被替代成ARM中的空操作,比如MOV R0,R0指令等

DC系列

DCB、DCW、DCD、DCQ:用于分配一段内存单元,并对其进行做初始化工作。
DCB:分配一段字节的内存单元,它每个操作数都占有一个字节,操作数范围为-128~255的数值或字符串。
DCW:分配一段半字的内存单元,它的每个操作数都占有两个字节,操作数是16位二进制数,取值范围为-32768~65535。
DCD:分配一段字的内存单元,它的每个操作数都占有4个字节,操作数可以是32位的数字表达式,也可以是程序中的标号。
DCQ:分配一段双字的内存单元,它的每个操作数都占有8个字节。
DCFS( DCFSU):为单精度浮点数分配一片连续的字存储单元并初始化
DCFD( DCFDU) 为双精度浮点数分配一片连续的字存储单元并初始化
SPACE 分配一片连续的存储单元并初始化为0

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

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

相关文章

Flink之转换算子和一些计算案例(Transformation)

Flink之转换算子 &#xff08;Transformation&#xff09; [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lcaNaXGY645b2f5adabd496ebbee9edfedad6437.png)null)] 数据源读入数据之后&#xff0c;我们就可以使用各种转换算子&#xff0c;将一个或多…

雷达算法 | 一种适用于汽车雷达的聚类算法研究与分析

本文参考TI的一种适用于汽车雷达的聚类算法研究和实现.pdf文档&#xff0c;原文链接如下&#xff1a;https://www.ti.com.cn/cn/lit/an/zhca739/zhca739.pdfts1672973254109&ref_urlhttps%253A%252F%252Fwww.google.com.hk%252F。 由于不涉及硬件&#xff0c;因此本文仅对…

C生万物 | 反汇编深挖【函数栈帧】的创建和销毁

&#x1f451;作者主页&#xff1a;Fire_Cloud_1 &#x1f3e0;学习社区&#xff1a;烈火神盾 &#x1f517;专栏链接&#xff1a;万物之源——C 一文彻底搞懂函数栈帧创建和销毁的过程一、 什么是函数栈帧二、 理解函数栈帧能解决什么问题呢&#xff1f;三、 函数栈帧的创建和…

易基因|糖尿病大血管和微血管病变的表观遗传学调控机制(DNA甲基化+组蛋白修饰):综述

大家好&#xff0c;这里是专注表观组学十余年&#xff0c;领跑多组学科研服务的易基因。2022年12月09日&#xff0c;《Frontiers in Endocrinology》杂志发表了题为“Epigenetic basis of diabetic vasculopathy”的综述文章&#xff0c;综述了表观遗传学修饰如DNA甲基化和组蛋…

电脑开机出现英文字母开不了机?小白操作技巧

在使用电脑的过程中&#xff0c;有时我们会遇到这种情况&#xff0c;就是电脑开机出现英文字母开不了机&#xff0c;而且还伴随着黑屏背景出现。出现这种问题&#xff0c;你们知道这是什么原因吗&#xff1f;以及我们该如何解决&#xff1f;下面这篇文章就可以告诉你&#xff0…

Foundry 中文文档发布啦

Foundry是一个Solidity智能合约开发工具链。Foundry管理您的依赖关系、编译项目、运行测试、部署&#xff0c;并允许您通过命令行和Solidity 脚本与链交互。 Foundry 中文文档是基于官方 Foundry book 的翻译&#xff0c;全面介绍 Foundry 所有功能。 使用Foundry的好处 Fou…

lvs负载均衡、nginx基本内容复习

文章目录前言一、LVSkeepalived实现高可用负载均衡二、三种不同模式实现负载均衡的区别与优缺点NAT模式DR直连路由模式TUN隧道模式三、Nginx之编译、负载均衡实现rr算法实现负载均衡ip_hash算法四、nginx平滑升级前言 一、LVSkeepalived实现高可用负载均衡 C/S架构和B/S架构&…

UWB室内定位系统的优势与好处

UWB定位系统的优势整理1、精度高&#xff1a;在室内定位领域&#xff0c;能够做到厘米级高精度定位的技术非UWB定位莫属。UWB采用TDOA&#xff08;到达时间&#xff09;算法&#xff0c;测量电磁波从发射端到达接收端所用的时间&#xff0c;分布在房间内的几个接收端同时接收到…

nginx小结二:高可用

nginx小结二&#xff1a;高可用nginx作为负载均衡器&#xff0c;所有请求都到了nginx&#xff0c;可见nginx处于非常重点的位置&#xff0c;如果nginx服务器宕机后端web服务将无法提供服务&#xff0c;影响严重。有鉴于此需要建立一个备份机&#xff0c;主服务器和备份机通过定…

用迭代局部搜索求解TSP问题(python)

文章目录1.迭代局部搜索(ILS)2.用ILS解决TSP问题2.1 函数模块2.2 主函数2.3 berlin52数据集测试1.迭代局部搜索(ILS) 关于迭代局部搜索(ILS iterated local search)的框架和应用总结可以阅读文献Iterated Local Search: Framework and Applications ILS的核心思想&#xff1a;…

【Kubernetes 企业项目实战】02、基于 Prometheus 和 K8s 构建智能化监控告警系统(下)

目录 一、可视化 UI 界面 Grafana 的安装和配置 1.1 Grafana 介绍 1.2 安装 Grafana 1.3 Grafana 界面接入 Prometheus数据源 1&#xff09;登录 grafana 2&#xff09;配置 grafana 界面 3&#xff09;导入的监控模板 二、kube-state-metrics 组件 2.1 kube-state-m…

JS的基础语法

作者&#xff1a;~小明学编程 文章专栏&#xff1a;JavaEE 格言&#xff1a;热爱编程的&#xff0c;终将被编程所厚爱。 目录 JavaScript的书写形式 行内式 内嵌式 外部式 注释 输入输出 输入 输出 JS的语法规则 变量 数据类型 数字类型 字符串类型 布尔类型 运算…

YED-M724嵌入式4G Cat1 核心板介绍

YED-M724嵌入式4G Cat1 核心板简介YEDM724 核心板是由银尔达&#xff08;yinerda&#xff09;基于合宙Air724 模组推出的低功耗&#xff0c;超小体积&#xff0c;高性能嵌入式4G Cat1 核心板。YED-M724嵌入式4G Cat1 核心板特点1、支持5-16V 供电&#xff1b;2、工作环境为-35℃…

基于轻量级YOLOV5融合RepVGG的电梯内电动车检测识别分析系统

RepVGG: Making VGG-style ConvNets Great Again 是2021 CVPR的一篇论文&#xff0c;正如他的名字一样&#xff0c;使用structural re-parameterization的方式让类VGG的架构重新获得了最好的性能和更快的速度。将RepVGG的设计思想融合进入到yolov5目标检测模型中是否有性能的提…

多线程案例-实现定时器

1.定时器是什么定时器是软件开发中的一个重要组件,功能是当达到一个特定的时间后,就执行某个指定好的代码定时器是一个非常常用的组件,特别是在网络编程中,当出现了"连接不上,卡了"的情况,就使用定时器做一些操作来止损标准库中也提供了定时器标准库中的Timer类标准库…

阿里妈妈Dolphin智能计算引擎基于Flink+Hologres实践

作者&#xff1a;徐闻春&#xff08;花名 陌奈&#xff09; 阿里妈妈事业部技术专家 本文整理至FlinkHologres实时数仓Workshop北京站&#xff0c;点击查看视频回放>>> 阿里妈妈数据引擎团队负责广告营销计算引擎Dophin的开发&#xff0c;目前支撑百万级广告主的营销…

ios打包证书申请流程

目前的APP开发&#xff0c;多端开发成为了主流&#xff0c;所以开发APP很多都是使用uniapp来开发&#xff0c;而且都是使用windows电脑来开发。但是在打包ios应用的时候&#xff0c;是需要一个p12格式的打包证书和profile描述文件的。 那么这两个文件如何申请呢&#xff1f;这…

关系抽取Casrel实现(Pytorch版)

前言 关系抽取是自然语言处理中的一个基本任务。关系抽取通常用三元组(subject, relation, object)表示。但在关系抽取中往往会面临的关系三元组重叠问题。《A Novel Cascade Binary Tagging Framework for Relational Triple Extraction》提出的CASREL模型可以有效的处理重叠关…

前端基础(十)_Dom自定义属性(带案例)

Dom自定义属性 1.1、为什么要用自定义属性 例&#xff1a;很多个 li 点击变颜色。 <ul><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8&…

LeetCode[373]查找和最小的K对数字

难度&#xff1a;中等题目&#xff1a;给定两个以 升序排列 的整数数组 nums1和 nums2, 以及一个整数 k。定义一对值 (u,v)&#xff0c;其中第一个元素来自 nums1&#xff0c;第二个元素来自 nums2。请找到和最小的 k个数对 (u1,v1), (u2,v2)... (uk,vk)。示例 1:输入: nums1 …