5. ARM_指令集

概述

分类

汇编中的符号:

  • 指令:能够编译生成一条32位机器码,并且能被处理器识别和执行
  • 伪指令:本身不是指令,编译器可以将其替换成若干条指令
  • 伪操作:不会生成指令,只是在编译阶段告诉编译器怎么编译

对于不同的CPU,指令和伪指令不同。因为指令和伪指令都由CPU来直接识别。

对于不同的编译器,伪操作不同,因为伪操作是控制编译器编译的。

ARM指令集的分类:

  • 数据处理指令:进行数学运算、逻辑运算
  • 跳转指令:实现程序的跳转,本质就是修改了PC寄存器
  • Load/Store指令:访问(读写)内存
  • 状态寄存器传送指令:用于访问(读写)CPSR寄存器
  • 软中断指令:触发软中断
  • 协处理器指令:操作协处理器的指令

其中数据处理指令、跳转指令、Load/Store指令是通用指令,任何一个CPU都具有该指令。并且这些指令在C语言中都有对应的语句。

指令格式:

汇编语言不区分大小写,但是不要出现一个指令里面既有大写也有小写。比如:可以写MOV或mov,但不要写成Mov 

立即数

什么是立即数:

立即数就是能够写在指令后面的数,例如 " MOV R0 #1 " 这个#1当中的数就是立即数。

立即数的本质就是包含在指令当中的数,属于指令的一部分。

注意:立即数不能写到32位,因为汇编指令转为机器码后是32位,这32位中有几位用来表示指令含义和寄存器含义,因此数据位并没有32位。

立即数与变量的区别:

立即数是指令的一部分,在使用立即数赋值时,CPU直接从机器码中就可以获取数据,不需要从内存中读取相应的值。

变量是存放在内存中,通过变量赋值,CPU必须先从内存中取出,再进行赋值。

32位非立即数却可赋值的情况:

当我们使用MOV R0, #0xFFFFFFFF这个指令时,0xFFFFFFFF是一个32位的数,一定不是一个立即数,但最终编译未出错。具体的编译器处理结果如下:

在这里,编译器将MOV R0, #0xFFFFFFFF 替换成了 MVN R0,#00000000,这个MVN的指令就是CPU可以识别执行的指令,原先的MOV就被称作伪指令。

条件码

条件码就是一个条件,当条件满足时执行这个操作,条件不满足时不执行该操作。

大多数的指令后都可以添加条件,具体示例见"跳转指令" - "2、B"

在使用条件码时,需要先使用CMP进行比较,之后再使用条件码进行条件执行。

条件码如下:

数据处理指令

1、数据搬移指令

1.1 MOV

将指定的数据搬移(赋值)到指定的寄存器中。

格式:

MOV 目标寄存器, 源操作数

目标寄存器: 可以为通用寄存器R0~R12,也可以是PC

源操作数:可以是立即数,也可以是寄存器

示例:

将立即数3搬移到寄存器R1,即:令R1=3

MOV R1, #3     @ #3代表十进制的3,#0x3代表十六进制的3

将R2寄存器的值搬移到寄存器R1,即:令R1=R2

MOV R1, R2

1.2 MVN

将指定的数据按位取反后,搬移(赋值)到指定的寄存器中。

格式: 

MVN 目标寄存器, 源操作数

示例:

将立即数0xFF取反后的值搬移到寄存器R1,即:令R1 = ~0xFF。

注意:这时R1存放的值为0xFFFFFF00,而不是0,因为ARM的寄存器是32位,所以在ARM寄存器中0xFF的存放值是0x000000FF,因此按位取反后为0xFFFFFF00,而不是0。

MVN R1 #0xFF

2、数值运算指令

一般格式:<操作码> <目标寄存器> <第一操作寄存器> <第二操作数>

  • 操作码:执行什么操作,如加减乘除
  • 目标寄存器:用于存放运算结果
  • 第一操作寄存器:必须是一个寄存器,是参与运算的数。
  • 第二操作数:可以是寄存器,也可以是立即数,这也是参与运算的数。

2.1 ADD

加法指令,将指定的两个数进行相加,结果存入指定的寄存器。

格式:

ADD 目标寄存器, 源寄存器, 源操作数

目标寄存器: 可以为通用寄存器R0~R12,也可以是PC

源寄存器:只能是寄存器

源操作数:可以是立即数,也可以是寄存器

示例:

已知R2=5,R3=3,实现R1=R2+R3

MOV R2,#5
MOV R3,#3
ADD R1,R2,R3 @ R1 = R2 + R3

已知R2=5,实现R1=R2+5

MOV R2,#5
ADD R1,R2,#5 @ R1 = R2 + 5
注意:这里不能写成ADD R1,#5,R2 对应ADD只有最后一个为源操作数

2.2 ADC

带进位的加法指令,将指定的两个数进行相加,并且会加上CPSR的进位。 

ADC实现64位运算:

实现:

0x00000001 00000002 + 0x00000003 00000004

思路:

将第一个数的低位和高位分别存放在R1、R2;将第二个数的低位和高位分别存放在R3、R4;将结果的低位和高位分别存放在R5、R6

运算代码:

MOV R1,0x00000002
MOV R2,0x00000001
MOV R3,0x00000004
MOV R4,0x00000003

ADDS R5,R1,R3 @将两个低位相加并允许设置CPSR
ADC R6,R2,R4  @将两个高位相加并加上CPSR的C位(溢出进位)

ADCS实现128位运算:

实现:

0x00000001 00000002 00000003 00000004 + 0x00000005 00000006 00000007 00000008

运算代码:

MOV R1,0x00000004
MOV R2,0x00000003
MOV R3,0x00000002
MOV R4,0x00000001

MOV R5,0x00000008
MOV R6,0x00000007
MOV R7,0x00000006
MOV R8,0x00000005

ADDS R9,R1,R5     @将两个低位相加并允许设置CPSR
ADCS R10,R2,R6    @将两个高位相加并加上CPSR的C位(溢出进位)并允许设置CPSR
ADCS R11,R3,R7    @将两个高位相加并加上CPSR的C位(溢出进位)并允许设置CPSR
ADC  R12,R4,R8    @将两个高位相加并加上CPSR的C位(溢出进位)

2.3 SUB

减法指令,将指定的两个数进行相减,结果存入指定的寄存器。

该指令只能实现 "寄存器 - 寄存器" 或者 "寄存器 - 立即数" 但实现不了 "立即数 - 寄存器"

格式:

SUB 目标寄存器, 源寄存器, 源操作数

目标寄存器: 可以为通用寄存器R0~R12,也可以是PC

源寄存器:只能是寄存器

源操作数:可以是立即数,也可以是寄存器

注意:SUB减法中有顺序,源寄存器存放的是被减数,源操作数存放的是减数。

示例:

已知R2=5,R3=3,实现R1=R2-R3

MOV R2,#5
MOV R3,#3
SUB R1,R2,R3 @ R1 = R2 - R3

已知R2=5,实现R1=R2-5

MOV R2,#5
SUB R1,R2,#5 @ R1 = R2 - 5
注意:这里不能写成SUB R1,#5,R2 对应SUB只有最后一个为源操作数

2.4 SBC

带借位的减法指令,将指定的两个数进行相减,并且会减去CPSR的借位(C位取反)。

SBC实现64位运算:

实现:

0x00000002 00000001 - 0x00000001 00000002

运算代码:

MOV R1,0x00000001
MOV R2,0x00000002
MOV R3,0x00000002
MOV R4,0x00000001

SUBS R5,R1,R4 @将两个低位相减并允许设置CPSR
SBC R6,R2,R5  @将两个高位相减并减去CPSR的C位取反(借位)

2.5 RSB

逆向减法指令,将指定的两个数进行相减,结果存入指定的寄存器。

该指令通过被减数与减数调换,解决了SUB不能实现"立即数 - 寄存器"的问题。

格式:

RSB 目标寄存器, 源寄存器, 源操作数

目标寄存器: 可以为通用寄存器R0~R12,也可以是PC

源寄存器:只能是寄存器

源操作数:可以是立即数,也可以是寄存器

注意:RSB减法中有顺序,源寄存器存放的是减数,源操作数存放的是被减数。这与SUB相反。

示例:

实现R1 = 3 - R2。

RSB R1,R2,#3     @ R1 = 3 - R2

2.6 MUL

乘法指令,将指定的两个数进行相乘,结果存入指定的寄存器。

格式:

MUL 目标寄存器, 源寄存器, 源寄存器

目标寄存器: 可以为通用寄存器R0~R12,也可以是PC

源寄存器:只能是寄存器

注意:乘法指令中只能是两个寄存器相乘,不能使用立即数。

示例:

实现R1 = R2 * R3。

MUL R1,R2,R3     @ R1 = R2 * R3

3、位运算指令

3.1 AND

按位与指令,将指定的两个数进行按位与,结果存入指定的寄存器。

格式:

AND 目标寄存器, 源寄存器, 源操作数

目标寄存器: 可以为通用寄存器R0~R12,也可以是PC

源寄存器:只能是寄存器

源操作数:可以是立即数,也可以是寄存器

示例:

实现R1 = R2 & R3。

AND R1,R2,R3     @R1 = R2 & R3

3.2 ORR

按位或指令,将指定的两个数进行按位或,结果存入指定的寄存器。

格式:

ORR 目标寄存器, 源寄存器, 源操作数

目标寄存器: 可以为通用寄存器R0~R12,也可以是PC

源寄存器:只能是寄存器

源操作数:可以是立即数,也可以是寄存器

示例:

实现R1 = R2 | R3。

ORR R1,R2,R3     @R1 = R2 | R3

3.3 EOR

按位异或指令,将指定的两个数进行按位异或,结果存入指定的寄存器。

格式:

EOR 目标寄存器, 源寄存器, 源操作数

目标寄存器: 可以为通用寄存器R0~R12,也可以是PC

源寄存器:只能是寄存器

源操作数:可以是立即数,也可以是寄存器

示例:

实现R1 = R2 ^ R3。

EOR R1,R2,R3     @R1 = R2 ^ R3

3.4 LSL

左移指令,将指定的数左移指定的位,结果存入指定的寄存器。

格式:

LSL 目标寄存器, 源寄存器, 源操作数

目标寄存器: 可以为通用寄存器R0~R12,也可以是PC

源寄存器:只能是寄存器

源操作数:可以是立即数,也可以是寄存器

示例:

实现R1 = R2 << 3

方式1:寄存器法
MOV R3,#3
LSL R1,R2,R3 @R1 = R2 << 3

方式2:立即数法
LSL R1,R2,#3 @R1 = R2 << 3

 3.4 LSR

右移指令,将指定的数右移指定的位,结果存入指定的寄存器。

格式:

LSR 目标寄存器, 源寄存器, 源操作数

目标寄存器: 可以为通用寄存器R0~R12,也可以是PC

源寄存器:只能是寄存器

源操作数:可以是立即数,也可以是寄存器

示例:

实现R1 = R2 >> 3

方式1:寄存器法
MOV R3,#3
LSR R1,R2,R3 @R1 = R2 >> 3

方式2:立即数法
LSR R1,R2,#3 @R1 = R2 >> 3

3.5 BIC

位清零指令,将指定的位进行清零,结果存入指定的寄存器。

格式:

BIC 目标寄存器, 源寄存器, 源操作数

目标寄存器: 可以为通用寄存器R0~R12,也可以是PC

源寄存器:只能是寄存器

源操作数:可以是立即数,也可以是寄存器

注意:清零源操作数为1的位数,为0的位数不进行操作。但源寄存器的数值不进行改变

示例:

已知R2=0xFF,实现将R2低四位清零,并把结果写入到R1中,并且R2值不进行改变。

MOV R2,#0xFF
BIC R1,R2,#0x0F @0x0F的低四位为1,所以R2的低4位被清零,结果存入到R1
                @运算之后R1=0xF0,R2=0xFF(值不改变)

4、其他

4.1 格式扩展

格式扩展示例:

MOV R3, R0, LSL #3 ; 将R0的值左移3位后存入R3

格式扩展指令的看法:

首先这里面有MOV、LSR这两个指令,最前面的MOV是操作码,所以这个整体指令的功能是数据搬移功能,因此R0为第一操作数,LSL #3为第二操作数。

这里的LSL #3并不是一个指令,含义是左移3,操作的数据源就是前面的R0,返回的结果存放在前面的R3。因此最终功能是将R0的值左移3位后存入R3。

4.2 运算影响CPSR

指令后加S影响CPSR:

默认情况下,数据运算不会对CPSR的条件位产生影响。当指令加上后缀 "S" 后,即可影响CPSR

MOV R1,#3
SUB R2,R1,#5   @这计算是一个负数,但没有加S后缀,所以CPSR的N位不置1

MOV R1,#3
SUBS R2,R1,#5  @这计算是一个负数,加了S后缀,所以CPSR的N位置1

跳转指令

1、CMP指令

比较指令,比较两个寄存器值中的关系,比较的结果存储再CPSR的NZCV中。

CMP的本质就是一条减法指令(SUBS),只是没有将运算结果存入寄存器。

格式:

CMP 源寄存器1 源寄存器2

当源寄存器1 == 源寄存器2时,CPSR中的 Z = 1。

当源寄存器1 != 源寄存器2时,CPSR中的 Z = 0。

当源寄存器1 < 源寄存器2时,CPSR中的 C = 0。

当源寄存器1 <= 源寄存器2时,CPSR中的 C = 0 或者 Z = 1。

当源寄存器1 > 源寄存器2时,CPSR中的 C = 1 且 Z = 0(相等时也不产生借位)。

当源寄存器1 >= 源寄存器2时,CPSR中的 C = 1。

示例:

实现1~100求和,结果存入R2。 

2、B

跳转到指定的位置。跳转指令的本质就是修改PC指向。

注意:默认情况下LR不会自动保存下一条指令的地址,加上后缀 "L" 可以允许LR保存下一条指令的地址。

B称为不带返回的跳转指令,BL称为带返回的跳转指令。

格式:

B 条件码 标签

条件码可以不写,当不写时为无条件跳转,当写时为有条件跳转。 条件码如下:

示例:

1、无返回跳转到FUNC标号下的第一条指令位置。

当执行 " B FUNC " 之后,PC将指向 "MOV R6,#6" 并在下一次执行该指令。

2、有返回跳转到FUNC标号下的第一条指令位置,执行之后再返回。

当执行 " BL FUNC " 之后,PC将指向 "MOV R6,#6" 并且 LR存储了 "MOV R4,#4"的位置。

当执行 " MOV PC,LR "之后,PC将指向 "MOV R4,#4" 实现了返回。

 3、条件跳转,当R1=R2时,跳转到FUNC

当指向 "BEQ FUNC" 后,因为R1==R2不成立,所以不跳转,继续执行 "MOV R3,#3" 指令

4、跳转到自身

指令 "B ." 代表跳转到自身。

比如 "B ." 存在0x00000004处,执行完该指令后PC依旧指向0x00000004

Load/Store指令

1、单寄存器内存访问

1.1 STR

将指定寄存器中的数据存储到指定的内存地址中。

指令与存放数据的字节数:

  • STR   -- 4字节
  • STRH -- 2字节
  • STRB -- 1字节

格式:

STR 源寄存器 [目标寄存器]

目标寄存器中存放内存的地址

注意:源寄存器中数据为多少字节,那么目标寄存器存放的地址就得为多少的整数倍。

示例:

将R1的数据写入到R2存放的地址的位置。

这里R2存放的0x40000000为内存,这是因为地址映射时规定了这个地址是内存的起始地址。

这里R1的数据为0xFF000000是4字节,因此R2存放的地址应该为4的整数倍,所以如果R2的值为0x40000001,这就是错误的地址。

1.2 LDR

将指定的内存地址中的数据读取到指定寄存器中。

指令与取出数据的字节数:

  • LDR   -- 4字节
  • LDRH -- 2字节
  • LDRB -- 1字节

 格式:

LDR 目标寄存器 [源寄存器]

源寄存器存放的是所需取数据的数据地址。

示例:

将R2中存放的地址的数据读出来,存放到R3当中。 

该代码运行结束后,R3就存放了0xFF000000

2、多寄存器内存访问

2.1 STM

将多个寄存器中的数据存储到指定的内存地址中。

格式:

STM 目标地址 {源寄存器}

源寄存器:当寄存器连续时,使用 "-"链接;当寄存器不连续时,使用 ","分隔。

如 "STM R11,{R1-R4}" 这操作的时R1、R2、R3、R4

如 "STM R11,{R1,R4}" 这操作的时R1、R4

示例:

将R1~R4寄存器的值存放到以某个地址为起点的地址空间

这里的R11没有加 "[ ]",但它的数据含义代表地址

列表顺序并不是真正的存储顺序, 存储顺序一定是小编号的寄存器存低地址数据。

如上述STM指令写成 "STM R11,{R1,R4,R2,R3}",存储顺序依旧是和 "STM R11,{R1-R4}"一致,而不是0x40000020存放R1,0x40000024存放R4....

2.2 LDM

将指定的内存地址中的数据读取到多个寄存器中。

格式:

LDM 读取起始地址 {目标寄存器}

目标寄存器:当寄存器连续时,使用 "-"链接;当寄存器不连续时,使用 ","分隔。

如 "LDM R11,{R6-R9}" 这操作的时R6、R7、R8、R9

如 "LDM R11,{R6,R9}" 这操作的时R6、R9

示例:

将某个地址为起点的地址空间的数据读取到R6~R9寄存器中

这里的R11没有加 "[ ]",但它的数据含义代表地址

列表顺序并不是真正的存储顺序, 存储顺序一定是小编号的寄存器存低地址数据。

如上述LDR指令写成 "LDR R11,{R6,R9,R7,R8}",存储顺序依旧是和 "LDR R11,{R6-R9}"一致。

状态寄存器传送指令

该指令常用于操作系统内部,比如刚上电时,初始化系统时使用该指令。

1、MRS

将CPSR的值读取到指定寄存器

格式:

MRS 目标寄存器 CPSR

示例: 

2、MSR

将指定数据写入到CPSR中

注意:特权模式下可以只写改变CPSR的值,User模式下不能直接改变CPSR的值。

 格式:

MSR CPSR 源操作数

示例:

软中断指令

1、SWI

该指令常用于操作系统内部,比如在User模式下调用系统调用时,Linux就会写一个SWI的指令将User模式转换成SVC模式,从而有足够的权限处理硬件。这个过程其实就是使用SWI指令将用户态切换到内核态。

格式:

SWI #参数

参数:这个值用于区分不同的硬件。用户态切换到内核态都是调用SWI来实现,但究竟调用哪一个硬件CPU并不清楚,此时CPU就需要该参数来得知调用哪一个硬件。

2、模拟实现软中断处理过程

流程描述:

  • 当程序复位,PC指向0x00处,0x00处存放了异常向量表Reset,跳转到MAIN函数。
  • 执行MAIN函数到SWI语句,产生了软中断异常。软中断异常是由SVC模式进行处理,所以CPU自动拷贝CPSR到SPSR_svc中,并且修改CPSR、保存返回地址到LR_svc,最后将PC指向异常向量表对应位置。对于软中断,对应地址为0x80,因此PC跳转到0x80。
  • PC到达0x80后执行跳转指令,跳转到中断处理函数。
  • 中断处理函数也是一个函数,因此需要先入栈保存现场,之后进行相关的操作,最后出栈恢复现场。在出栈时,加上 "^" 符号可以自动将SPSR_svc的数据拷贝到CPSR恢复现场,同时出栈数据可以直接写到PC中,一步实现出栈、恢复现场、跳转。

实验代码如下:

.text
.global _start
_start:

	@异常向量表
	B MAIN				@Reset 			0x00
	B .					@Undef			0x04
	B SWI_Handler		@SWI			0x08
	B .					@Prefetch Abort	0x0C
	B .					@Data Abort		0x10
	B .					@Reserved		0x14
	B .					@IRQ			0x18
	B . 				@FIQ			0x20

	@MAIN中实现R3=R1+R2,并调用一次SWI
MAIN:
	MOV SP,#0x40000020 	@初始化SP,这里是SVC模式下的SP
	MSR CPSR,#0x10	  	@将模式改为User模式,IRQ/FIQ使能
	MOV R1,#1
	MOV R2,#2
	SWI #1				@调用SWI,#1用于区分硬件
	ADD R3,R1,R2
	B STOP

	@SWI_Handler是SWI的中断处理函数,这里也实现R3=R1+R2的功能
SWI_Handler:
	STMFD SP!,{R1,R2,LR}		@入栈保护现场
	MOV R1,#20
	MOV R2,#30
	ADD R3,R1,R2
	LDMFD SP!,{R1,R2,PC}^	@将LR的数据出栈到PC,并把SPSR的值拷贝到CPSR(^的作用)

STOP:
	B STOP

.end

协处理器指令

协处理器指令的分类可以分为:

  • 数据运算指令CDP
  • 存储器访问指令STC、LDC
  • 寄存器传送指令MRC、MCR,用于在协处理器和ARM处理器中的寄存器进行数据交互。

伪指令

1、NOP

NOP是让程序什么都不干,暂停一个机器周期。最终编译之后NOP会被编译成MOV R0,R0

2、LDR

LDR的格式不同,含义也不同。当为 "LDR R1,[R2]" 这种格式时,LDR是一个指令;伪指令的情况有以下情况:

1、赋值任意32位数

当为 "LDR R1,=0x12345678" 这种格式时,LDR是一个伪指令,代表R1=0x12345678。该伪指令可以将任意32位数搬移到寄存器。LDR R1,=0x12345678的转换过程如下:

  • 0x12345678将作为一个不被执行的机器码存放到内存中,这条机器码被存放在全部有效指令之后,在下图中存放在0x58处,因为0x54是最后一条有效指令。
  • LDR的指令将被译码为 "LDR R1,[PC,#偏移值]" 这种格式,在下图中指令被存放在0x30,因为三级流水线的原因,此时PC=0x30+8,因此偏移值 = 0x20。
  • 最终拿到的值是0x58地址当中的数据,就是0x12345678,实现了任意32位数据的赋值。

2、通过标号将地址写入寄存器

当为 "LDR R1,=STOP" 这种格式时,LDR是一个伪指令,代表将STOP标号的地址值存入R1中。

编译后的指令同样是转换成PC加偏移量模式,PC偏移量计算与LDR R1,=0x12345678这种计算方法一样。

3、通过标号将地址当中的值写入寄存器

当为 "LDR R1,STOP" 这种格式时,LDR是一个伪指令,代表将STOP标号的地址当中的值存入R1中。

编译后的指令同样是转换成PC加偏移量模式,PC偏移量计算与LDR R1,=0x12345678这种计算方法一样。

伪操作

伪操作通常以 "." 开头。

1、全局/局部声明

格式:

.global <符号名> 

.local <符号名> 

作用:

将符号声明为全局/局部。

当声明为全局时,所有.s都能访问;当声明为局部时,只有当前.s能访问。

2、宏

格式:

.equ <宏名>,值

作用:

与C语言的#define一样,原值替代。

3、语句封装

格式:

.macro <符号>

@汇编语句

.endm

作用:

类似函数,函数名就是.macro后面跟的符号

4、条件编译

格式:

.if

@汇编语句

.endif

作用:

类似#if #endif,条件满足时才进行编译。

5、重复编译

格式:

.rept <次数>

@汇编语句

.endr

作用:

将区域中的汇编语句重复编译指定次数。

6、弱化符号

格式:

.weak <符号>

作用:

弱化指定的符号,当使用到该符号但未定义该符号时,编译器依旧不报错。

当弱化了符号,并且符号未定义时,编译器会将调用该符号的指令变为NOP,即:一个空操作。

7、申请空间

格式:

.word <初始化值>         @32位,一个字

.byte <初始化值>         @8位,一个字节
.align <以多少字节对齐>  @写3,代表以2^3对齐

.space <申请字节数> <初始化值> @申请指定字节存放数据

.word作用:

在当前指令的地址位置申请空间,并初始化。

.byte作用:

注意:.byte申请空间后,需要再申请冗余空间来进行地址对齐。

.space作用:

注意:.space申请空间后,不一定需要.align来对齐,比如上述是12给字节空间,申请之后地址就是对齐的。

8、标注

格式:

.arm             @告诉编译器这之后是arm指令
@ARM汇编指令

.thumb           @告诉编译器这之后是thumb指令
@Thumb汇编指令    

.text            @告诉编译器这之后是代码段

.end             @告诉编译器汇编代码已结束

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

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

相关文章

小程序租赁系统开发为企业提供高效便捷的租赁服务解决方案

内容概要 在这个数字化飞速发展的时代&#xff0c;小程序租赁系统应运而生&#xff0c;成为企业管理租赁业务的一种新选择。随着移动互联网的普及&#xff0c;越来越多的企业开始关注如何利用小程序来提高租赁服务的效率和便捷性。小程序不仅可以为用户提供一个快速、易用的平…

计算机组成原理——高速缓存

标记表示——主存块号和缓存块之前的一一对应关系

赛元免费开发板申请

在作者网上冲浪的时候&#xff0c;突然发现了一个国内的良心企业&#xff0c;虽然现在不是很有名&#xff0c;但是他现在是有一个样品申请的活动&#xff0c;他就是国内的Redfine新定义&#xff0c;他申请的板子是用的赛元MCU&#xff0c;作者本着有板子就要申请的原则&#xf…

Ubuntu 的 ROS 操作系统 turtlebot3 SLAM仿真

引言 SLAM&#xff08;同步定位与地图构建&#xff09;在Gazebo仿真环境中的应用能够模拟真实机器人进行环境建图和导航。通过SLAM仿真&#xff0c;开发者可以在虚拟环境中测试算法&#xff0c;而不必依赖真实硬件&#xff0c;便于调试与优化。 Gazebo提供了多个虚拟环境&…

【解决】Layout 下创建槽位后,执行 Image 同步槽位位置后表现错误的问题。

开发平台&#xff1a;Unity 6.0 编程语言&#xff1a;CSharp 编程平台&#xff1a;Visual Studio 2022   一、问题背景 | 开发库存系统 图1 位置同步失败问题 图2 位置正常同步效果表现 黑框 作用于 UnityEngine.UI.GridLayoutGruop&#xff0c;形成 4x6 布局&#xff0c;如…

红日靶场-1详细解析(适合小白版)

红日靶场涉及内网知识&#xff0c;和前期靶场不太一样&#xff0c;前期靶场大部分都是单个靶机获得root权限&#xff0c;而这一次更综合&#xff0c;后期也会继续学习内网知识&#xff0c;继续打红日靶场&#xff0c;提高自己的综合技能。 环境搭建 首先本题的网络拓扑结构如…

LabVIEW大数据处理

在物联网、工业4.0和科学实验中&#xff0c;大数据处理需求逐年上升。LabVIEW作为一款图形化编程语言&#xff0c;凭借其强大的数据采集和分析能力&#xff0c;广泛应用于实时数据处理和控制系统中。然而&#xff0c;在面对大数据处理时&#xff0c;LabVIEW也存在一些注意事项。…

小米路由器用外网域名访问管理界面

本文在Redmi AX3000 (RA81)设置&#xff0c;其他型号路由器的管理界面端口可能各不相同。 开始之前需要保证路由器SSH功能正常&#xff0c;如果没有SSH可以参考这里。 1. 给WAN口开放80端口 可以通过下载mixbox的firewall插件或者其他防火墙插件开放端口。 2. 把域名解析到路…

【AI图像生成网站Golang】雪花算法

AI图像生成网站 目录 一、项目介绍 二、雪花算法 三、JWT认证与令牌桶算法 四、项目架构 五、图床上传与图像生成API搭建 六、项目测试与调试(等待更新) 雪花算法 雪花算法 (Snowflake) 是一种高效、可扩展的分布式唯一ID生成算法&#xff0c;最早由 Twitter 开发&…

【计算机网络】协议定制

一、结构化数据传输流程 这里涉及协议定制、序列化/反序列化的知识 对于序列化和反序列化&#xff0c;有现成的解决方案&#xff1a;①json ②probuff ③xml 二、理解发送接收函数 我们调用的所有发送/接收函数&#xff0c;根本就不是把数据发送到网络中&#xff01;本质都是…

用sqlmap工具打sqli-labs前20关靶场

这个星期我们用手动注入打了前20关靶场&#xff0c;今天我们用sqlmap直接梭哈前20关 1.介绍sqlmap sqlmap是一个自动化的SQL注入工具&#xff0c;其主要功能是扫描&#xff0c;发现并利用给定的URL和SQL注入漏洞。 2.下载和使用sqlmap 官方下载地址&#xff1a;GitHub - sq…

Unreal engine5实现类似鬼泣5维吉尔二段跳

系列文章目录 文章目录 系列文章目录前言一、实现思路二、具体使用蓝图状态机蓝图接口三、中间遇到的问题 前言 先看下使用Unreal engine5实现二段跳的效果 一、实现思路 在Unreal Engine 5 (UE5) 中使用蓝图系统实现类似于《鬼泣5》中维吉尔的二段跳效果&#xff0c;可以通…

【大数据学习 | flume】flume之常见的sink组件

Flume Sink取出Channel中的数据&#xff0c;进行相应的存储文件系统&#xff0c;数据库&#xff0c;或者提交到远程服务器。Flume也提供了各种sink的实现&#xff0c;包括HDFS sink、Logger sink、Avro sink、File Roll sink、HBase sink&#xff0c;。 ​ Flume Sink在设置存…

C++构造函数详解

构造函数详解&#xff1a;C 中对象初始化与构造函数的使用 在 C 中&#xff0c;构造函数是一种特殊的成员函数&#xff0c;它在创建对象时自动调用&#xff0c;用来初始化对象的状态。构造函数帮助我们确保每个对象在被创建时就处于一个有效的状态&#xff0c;并且在不传递任何…

最小的子数组(leetcode 209)

给定一个正整数数组&#xff0c;找到大于等于s的连续的最小长度的区间。 解法一&#xff1a;暴力解法 两层for循环&#xff0c;一个区间终止位置&#xff0c;一个区间起始位置&#xff0c;找到大于等于s的最小区间长度&#xff08;超时了&#xff09; 解法二&#xff1a;双指…

应用系统开发(10) 钢轨缺陷的检测系统

涡流检测系统框图 其中信号发生器为一定频率的正弦信号作为激励信号&#xff0c;这个激励信号同时输入给交流电桥中的两个检测线圈&#xff0c;将两个线圈输出的电压差值作为差分信号引出至差分放大电路进行放大&#xff0c;经过放大后信号变为低频的缺陷信号叠加在高频载波上…

结构化需求分析与设计

前言: 感觉书本上和线上课程, 讲的太抽象, 不好理解, 但软件开发不就是为了开发应用程序吗?! 干嘛搞这么抽象,对吧, 下面是个人对于软件开发的看法, 结合我的一些看法, 主打简单易懂, 当然,我一IT界小菜鸟, 对软件开发的认识也很浅显, 这个思维导图也仅仅是现阶段我的看…

列出D3的所有交互方法,并给出示例

D3.js 提供了丰富的交互方法&#xff0c;可以用来增强图表的用户交互体验。以下是一些常用的交互方法及其示例&#xff1a; 1. 鼠标事件 on("mouseover", function) 用途: 当鼠标悬停在元素上时触发。示例:svg.selectAll(".bar").on("mouseover&qu…

【传知代码】VRT_ 关于视频修复的模型

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀ VRT_ 关于视频修复的模型 背景介绍&#xff1a;重要性&#xff1a; VRT的重要性和研究背景VRT的背景&#xff1a;VRT的重要性&#xff1a; 视…

软考教材重点内容 信息安全工程师 第 4 章 网络安全体系与网络安全模型

4,1 网络安全体系的主要特征: (1)整体性。网络安全体系从全局、长远的角度实现安全保障&#xff0c;网络安全单元按照一定的规则&#xff0c;相互依赖、相互约束、相互作用而形成人机物一体化的网络安全保护方式。 (2)协同性。网络安全体系依赖于多种安全机制&#xff0c;通过各…