ARM笔记-ARM指令集

第三章 ARM指令集

3.1 ARM指令集简介

  • ARM微处理器的ARM指令集 ,所有的指令长度都是32位 ,并且大多数指令都在一个单独指令周期内执行
    • 主要特点:
      • 指令是条件执行的
      • ARM微处理器的指令集是加载/存储型的
      • 在多寄存器操作指令中一次最多可以完成 16个寄存器的数据传送

3.1.1 ARM指令格式

一、 ARM指令格式

<opcode>{<Condition>}{S} {<Rd>}{,<Rn>}{,<Operand2>}

  • 格式中< >的内容必不可少,{ }中的内容可省略。

    • <opcode>表示操作码,如ADD表示算术加法
    • {<cond>}表示指令执行的条件域,如EQ、NE等
    • {S}决定指令的执行结果是否影响CPSR的值,使用该后缀则指令执行的结将果影响CPSR的值,否则不影响。
    • <Rd>表示目标或源寄存器
    • <Rn>表示第一个操作数,为寄存器
    • <Operand2>表示第二个操作数,可以是立即数、寄存器和寄存器移位操作数
  • 除了<opcode>其余域都可以选择使用。

  • 举例

    例如: 指令ADDEQS R0,R1,#8;操作码为ADD,条件域cond为EQ,S表示该指令的执行影响CPSR寄存器的值,目的寄存器Rd为R0,第一个操作数寄存器Rn为R1,第二个操作数OP2为立即数#8。执行结果:R0 = R1+ 8
    
二、 指令的机器码
  • 从形式上看,ARM指令在机器中的表示格式是用32位的二进制数表示。
    • 如ARM中有一条指令为:
      • ADDEQS R0, R1, #8
      • 其二进制代码形式为
31~2827~2524~212019~1615~1211~0
00000010100100010000000000001000
condopcodesRnRdOp2
  • ARM指令一般可以分为5个域

    • 第1个域–4位
      • 4位[31:28]的条件码域,4位条件码共有16种组合
    • 第2个域–8位
      • 指令代码域[27:20],除了指令编码外,还包含几个很重要的指令特征和可选后缀的编码
    • 第3个域–4位
      • 第1个操作数寄存器Rn,是4位[19:16],为R0~R15共16个寄存器编码
    • 第4个域–4位
      • 目标或源寄存器Rd,是4位[15:12],为R0~R15共16个寄存器编码
    • 第5个域–12位
      • 第二个操作数[11:0]
三、指令的可选后缀
  1. S后缀

    • 指令中使用S后缀时,指令执行后,CPSR的条件标志位将被刷新
    • 不使用S后缀时,指令执行后,CPSR的条件标志将不会发生变化。
    例:假设R0=0x1,R3=0x3,指令执行之前CPSR部分标志位为 nZcv,分别执行如下指令CPSR的值有何变化?SUB R1,R0,R3SUBS R1,R0,R3
    
    • 分析:
      • 执行第1条指令对于标志寄存器的值没有任何影响,因此CPSR的值不变。
      • 执行第2条指令后CPSR=Nzcv。
  2. !后缀

    • 如果指令地址表达式中不含!后缀,则基址寄存器中的地址值不会发生变化。

    • 指令中的地址表达式中含有!后缀时,指令执行后,基址寄存器中的地址值将发生变化,变化的结果如下:

      • 基址寄存器中的值(指令执行后)=指令执行前的值+地址偏移量
      例:分别执行下面两条指令有何区别?LDR R3,[R0,#4] LDR R3,[R0,#4]!
      
      • 分析:
        • 第1条指令没有!后缀,指令的结果是把R0加4作为地址指针,把这个指针所指向的地址单元所存储的数据读入R3,R0的值不变
        • 第2条指令除了实现以上操作外,还把R0+4的结果送到R0中
    • 使用!后缀需要注意如下事项:

      • !后缀必须紧跟在地址表达式后面,而地址表达式要有明确的地址偏移量
      • !后缀不能用于R15(PC)的后面
      • 当用在单个地址寄存器后面时,必须确信这个寄存器有隐性的偏移量
        • 例如“STMIA R7!, {R0 – R3}”
          • 此时地址基址寄存器R7的隐性偏移量是16字节(因为连续压栈了4个寄存器的值,每一个寄存器的值为4字节长度,即一个字)
          • 如果R7的初始值为 0X40000000,则该语句结束后为0X40000010
  3. B后缀

    • 指令所涉及的数据是一个字节,不是一个字或半字
    LDR R4,[R0]R4=[R0],指令传送一个字
    LDRB R4,[R0]R4=[R0],指令传送一个字节
    LDREQB R4,[R0]如果相等则执行,R4=[R0],指令传送一个字节

3.1.2 ARM指令的条件码

  • 当处理器工作在 ARM状态时,几乎所有的指令均能根据CPSR中的条件标志位的状态和指令的条件域有条件地执行。

    • 当指令的执行条件满足时,指令被执行,否则指令被忽略
    • 条件后缀只影响指令是否执行,不影响指令的内容
  • ARM指令的条件码助记符如下表所示:(不用记)

    条件码条件码助记符CPSR中条件标志位值含义
    0000EQZ=1相等
    0001NEZ=0不相等
    0010CS/HSC=1无符号数大于或等于
    0011CC/LOC=0无符号数小于
    0100MIN=1负数
    0101PLN=0正数或零
    0110VSV=1溢出
    0111VCV=0未溢出
    1000HIC=1且Z=0无符号数大于
    1001LSC=0或Z=1无符号数小于或等于
    1010GEN=V带符号数大于或等于
    1011LTN!=V带符号数小于
    1100GTZ=0且N=V带符号数大于
    1101LEZ=1或N!=V带符号数小于或等于
    1110AL无条件执行
    1111NVARMV3之前从不执行(不要使用)
    • 条件后缀和S后缀的关系
      • 如果既有条件后缀又有S后缀,则书写时S排在后面
        • 如:ADDEQS R1,R0,R2
          • 该指令在Z=1时执行,将R0+R2的值放入R1,同时刷新条件标志位
      • 条件后缀是要测试条件标志位,而S后缀是要刷新条件标志位
      • 条件后缀要测试的是执行前的标志位,而S后缀是依据指令的结果改变条件标志

3.1.3 ARM指令分类

  • ARM 指令可以分为:分支指令、数据处理指令、存储访问指令、协处理器指令、杂项指令五类。
  1. 分支指令:分支指令用于控制程序的执行流程实现ARM代码与Thumb代码之间进行切换
  2. 数据处理指令:数据处理指令在通用寄存器上执行计算
    • 主要分为3种:算术/逻辑指令、比较指令和乘法指令。
  3. 存储访问指令:用于 加载/存储 存放于MCU片外存储系统中的数据
    • 加载指令用于从内存中读取数据放入寄存器中
    • 存储指令用于将寄存器中的数据保存到内存中
  4. 协处理器指令:ARM协处理器指令用于控制外部的协处理器。包括:
    • 数据处理指令:启动一个协处理器专用的内部操作。
    • 数据转移指令:使数据在协处理器和存储器之间进行转移。
    • 寄存器转移指令:协处理器值转移到ARM寄存器或ARM寄存器的值转移到协处理器。
  5. 杂项指令:包括状态寄存器转移指令异常中断产生指令
    • 状态寄存器转移指令
      • 将CPSR或SPSR的内容转移到一个通用寄存器,或者反过来将通用寄存器的内容写入CPSR或SPSR寄存器
    • ARM有两条异常中断产生指令,分别为 软中断指令SWI断点中断指令BKPT

3.2 指令寻址方式

3.2.1 立即数寻址

  • 立即数寻址也叫立即寻址,操作数本身就在指令中给出取出指令也就取到了操作数。这个操作数被称为立即数,对应的寻址方式也就叫做立即数寻址。

    • 立即数要求以“#”为前缀

      • 对于以十六进制表示的立即数,还要求在“#”后加上**“0x”或“&”**
      • 对于以二进制表示的立即数,要求在“#”后加上**“0b”**
      • 对于以十进制表示的立即数,要求在“#”后加上**“0d”或缺省**
    • 举例

      • MOV R0, #15 ; R0←#15

        • 此指令是将立即数15传送到R0中,该指令的机器编码为E3A0000FH(H表示16进制)

        • 由指令编码中0x00F即可得到一个32位的立即0x0000000FH,这个数再送入R0

      • Q:如何在指令编码中表达32位立即数?

      • A:

3.2.2 寄存器寻址

  • 寄存器寻址就是利用寄存器中的数值作为操作数,这种寻址方式是各类微处理器经常采用的一种方式,也是一种执行效率较高的寻址方式
    • 例:
      • MOV R1,R2 ;R1←R2
      • ADD R0,R1,R2 ;R0←R1+R2

3.2.3 寄存器移位寻址

  • 第二操作数为寄存器型时,在执行寄存器寻址操作时,也可以对第二操作数寄存器进行移位,此时第二操作数形式为:
    • ADD Rd, Rn, Rm,{<shift>}
      • 其中:
        • Rm:称为第二操作数寄存器
        • <shift>:用来指定移位类型和移位位数,有两种形式:
          • 5位立即数(其值小于32)
          • 寄存器(用Rs表示)(其值小于32)
  • 在指令执行时,将寄存器移位后的内容,作为第二操作数参与运算。
    • 例如指令:
      • ADD R3,R2,R1,LSR #2 ;R3←R2+(R1右移2位)
      • ADD R3,R2,R1,LSR R0 ;R3←R2+(R1右移R0位)
  • 第二操作数的移位方式
    • LSL 逻辑左移 :
      • 逻辑左移,空出的最低有效位用0填充。
      • SUB R3,R2,R1,LSL #2 ;R3←R2-(R1左移2位)
    • LSR 逻辑右移 :
      • 逻辑右移,空出的最高有效位用0填充。
      • SUB R3,R2,R1,LSR R0 ;R3←R2-(R1右移R0位)
    • ASL 算术左移 :
      • 算术左移,由于左移空出的有效位用0填充,因此它与LSL同义。
    • ASR 算术右移 :
      • 算术右移 (Arithmetic Shift Right) 。算术移位的对象是带符号数,移位过程中必须保持操作数的符号不变。如果源操作数是正数,空出的最高有效位用0填充,如果是负数用1填充
    • ROR 循环右移
      • 循环右移(Rotate Right),移出的字的最低有效位依次填入空出的最高有效位
    • RRX 带扩展的循环右移
      • 带进位位的循环右移(Rotate Right Extended) 。将寄存器的内容循环右移1位,空位用原来C标志位填充
      • SUB R3,R2,R1,RRX ;R3←R2-(R1带进位位循环右移1位)
  • 第二操作数的移位位数
    • 移位位数可以用立即数方式或者寄存器方式给出其值均小于32,应为0—31
    • 如下所示:
      • ADD R3,R2,R1,LSR #2 ;R3=R2+(R1右移2位)
      • ADD R3,R2,R1,LSR R4 ;R3=R2+(R1右移R4位)
      • 寄存器R1的内容分别逻辑右移2位、R4位,再与寄存器R2的内容相加,结果放入R3中。

3.2.4 寄存器间接寻址

  • 寄存器间接寻址就是以寄存器中的值作为操作数的地址,而操作数本身存放在存储器中
    • 例:LDR R0,[R4] ;R0←[R4]

3.2.5 基址变址寻址

  1. 变址寻址

    • 也叫基址变址寻址:将基址寄存器的内容与指令中给出的地址偏移量相加,得到操作数所在的存储器的有效地址。

    • 变址寻址方式常用于访问某基地址附近的地址单元。(4K范围的偏移)

      • 例如: LDR R0,[R1,#4] ;R0←mem32[R1+4]
  2. 加偏移地址的方式

    • 前变址模式(不修改基址寄存器)

      • 基址+偏址,生成操作数地址,再做指令指定的操作。也叫前索引偏移

    • 自动变址模式(修改基址寄存器):

      • 基址+偏址,生成操作数地址,做指令指定的操作
      • 然后自动修改基址寄存器
        • 例如:LDR R0,[R1,#4]!
          • 先 R0←mem32 [R1+4]
          • 然后 R1←R1+4
          • ! 表示更新基址寄存器。
    • 后变址模式(修改基址寄存器):

      • 基址寄存器不加偏移作为操作数地址

      • 完成指令操作后,用(基址+偏移)的值修改基址寄存器

      • 先用基地址传数,然后修改基地址(基址+偏移),也叫后索引偏移

  3. 偏移地址形式

    • 可以是一个立即数,也可以是另一个寄存器,并且还可以是寄存器移位操作

      • 常用的是立即数偏移的形式。
    • 如下所示:

      • LDR R2,[R3,#0X0C] ;R2< —[R3+0X0C]

      • STR R1,[R0,#-0x4]!

        • ;R1 —>mem32[R0-4],
        • ;R0=R0-4
      • LDR r0,[r1,r2] ;r0<—mem32[r1+r2]

      • LDR r0,[r1,r2,LSL #2] ;r0<—mem32[r1+r2*4]]

3.2.6 多寄存器寻址

  • 采用多寄存器寻址方式,一条指令可以完成多个寄存器值的传送
  • 这种寻址方式是多寄存器传送指令 LDM/STM 的寻址方式,这种寻址方式中用一条指令最多可传送16个通用寄存器的值
  • 连续的寄存器间用 - 连接,否则用 , 分隔。
    • LDMIA R0!,{R1-R4} ;R1←**[R0]、R2←[R0+4]、R3←[R0+8]、R4←[R0+12]**
  • 注意:
    • 对于所有LDM/STM指令而言,寄存器序号低的,在低地址单元序号大的在高地址单元
    • 与书写顺序无关!

  • 4种寻址操作
    • LDMIA/STMIA Increment After(先传送,后地址加4)
    • LDMIB/STMIB Increment Before(先地址加4 ,后传送)
    • LDMDA/STMDA Decrement After(先传送,后地址减4)
    • LDMDB/STMDB Decrement Before (先地址减4,后传送)

3.2.7 堆栈寻址

  • 堆栈是一种数据结构,按后进先出(Last In First Out, LIFO)的方式工作,使用一个称作堆栈指针的专用寄存器指示当前的操作位置,堆栈指针总是指向栈顶。

  • 堆栈可分为两种增长方式

    • 向上生长:向高地址方向生长,称为递增堆栈
    • 向下生长:向低地址方向生长,称为递减堆栈
  • 根据堆栈指针指向的数据位置的不同,可分为:

    • 满堆栈:堆栈指针指向最后压入堆栈的有效数据项,称为满堆栈;
    • 空堆栈:堆栈指针指向下一个待压入数据的空位置,称为空堆栈。
  • 这样就有4种类型的堆栈表示递增和递减的满和空堆栈的各种组合。

    • 四种类型的堆栈工作方式
      • 满递增堆栈FA(Full Ascending):堆栈指针指向最后压入的数据,且由低地址向高地址生长。
      • 满递减堆栈FD(Full Descending) :堆栈指针指向最后压入的数据,且由高地址向低地址生长。
      • 空递增堆栈EA(Empty Ascending):堆栈指针指向下一个将要放入数据的空位置,且由低地址向高地址生长。
      • 空递减堆栈ED(Empty Descending):堆栈指针指向下一个将要放入数据的空位置,且由高地址向低地址生长。
    • 也就是说上面的递增递减都指的是堆栈生长方向,即入栈时递增还是递减

3.2.8 相对寻址

  • 与基址变址寻址方式相类似,相对寻址以程序计数器PC的当前值为基地址,指令中的地址标号作为偏移量,将两者相加之后得到操作数的有效地址。

3.3 ARM指令集

3.3.1 分支指令

  • 在ARM中有两种方式可以实现程序的跳转:

    • 一种是使用分支转移指令直接跳转
    • 另一种则是直接向PC寄存器赋值来实现跳转
  • ARM的分支转移指令,可以从当前指令向前或向后的32MB的地址空间跳转,根据完成的功能它可以分为以下4种

一、B & BL
  • B 指令与 BL 指令的编码格式如下:

    • 从编码中看到L控制了PC与LR寄存器之间的开关
      • 当L=0 时,该开关断开,指令为B指令;
      • 当L=1时,该开关接通,指令为BL指令。
    • Signed_immed_24表示24位有符号的立即数(偏移量
  • B 和 BL 指令的助记符格式为:

    • B{<cond>} <target>和BL{<cond>} <target>
      • cond表示指令执行条件
      • target表示跳转地址
      • 功能:跳转到指定地址执行,地址范围限制在当前PC寄存器所指向的指令地址的±32MB范围
    • 跳转指令也叫程序转移指令
    • 写汇编程序时,可以跳转到一个绝对地址,如:
      • B 0x1234 (注: B #0x1234是错误的
      • 编译器会把该绝对地址转换为相对地址放入指令中
  • signed_immed_24 间接提供目标地址真正的目标地址是由处理器根据这个有符号数和当前的PC值计算出来的

    • 具体计算为:
      • 先将 signed_immed_24 左移两位(即具有26位的偏移量),并扩展为32位有符号数
      • 然后再将这32位有符号数与 PC 的当前值相加,得到实际的跳转地址。
      • 因此B 和 BL 指令转移的偏移量为 26 位,即转移的跨度为前后 32MB 地址空间
  • B和BL的区别:

    • BL在跳转之前会把BL指令的下一条指令地址(断点地址)保存到连接寄存器 LR(R14),因此程序在必要的时候可以通过将 LR 的内容加载到 PC 中,使程序返回到跳转点。
    • BL 指令经常被用来调用一个子程序。
二、BX
  • BX 指令的格式:

    • BX{<cond>} Rm
    • cond表示指令执行条件
    • Rm寄存器,值是绝对地址值,不是偏移量,在指令执行后,Rm中的地址值与#0XFFFF FFFE 进行 “与” 运算,再被复制到程序计数器PC。
      • Rm[0]为1时,强制程序从ARM指令状态跳转到Thumb指令状态。
      • Rm[0]为0时,强制程序从Thumb 指令状态跳转到ARM指令状态。
    • 功能: 跳转到指令中所指定的目标地址,并实现状态切换。(T<-Rm[0]
  • 指令编码格式

三、BLX
  • BLX 指令的格式有两种:
    • BLX <target>BLX{<cond>} Rm
      • 以target方式提供目标地址的 BLX 指令的功能是:
        • 把程序跳转到指令中所指定的目标地址继续执行,并同时将处理器的工作状态从ARM状态切换到Thumb状态,并将下一条的地址保存到寄存器 LR 中。
      • 以 Rm 方式提供目标地址的 BLX 指令,除了跳转和下一条的地址保存到LR之外,也可进行状态切换,但其切换的依据是Rm最低位的值
        • 如果值为0 ,则目标地址处应为 ARM指令
        • 如果值为1 ,则目标地址处应为 Thumb 指令
四、长跳转
  • 另一种实现指令跳转的方式是通过直接向 PC 寄存器中写入目标地址值,实现在4GB 地址空间中任意跳转,这种跳转又称为长跳转
  • 如果在长跳转指令之前使用“MOV LR,PC” 等指令,可以保存将来返回的地址值,也就实现了在 4GB 的地址空间中的子程序调用。

3.3.2 数据处理指令

一、数据处理指令概述
  1. ARM数据处理指令的功能

    • 主要完成寄存器中数据的算术和逻辑运算操作。
  2. ARM数据处理指令的特点

    • 操作数来源:所有的操作数要么来自寄存器,要么来自立即数,不会来自存储器
    • 操作结果:如果有结果,则结果一定是为32位宽、或64位宽(长乘法指令),并且放在一个或两个寄存器中,不会写入存储器
    • 有第二个操作数(除了乘法指令)Operand2 :切记其三种形式:立即数、寄存器、寄存器移位。
    • 乘法指令的操作数:全部是寄存器。
  3. ARM数据处理指令分类

    • 22条可分为5类:
      • 算术运算指令:ADD ADC SUB SBC RSB RSC MUL MLA UMULL UMLAL SMULL SMLAL
      • 逻辑运算指令:AND ORR EOR BIC
      • 数据传送指令:MOV MVN
      • 比较指令:CMP CMN
      • 测试指令:TST TEQ
    • 上述指令只能对寄存器操作,不能针对存储器
  4. 数据处理指令对程序状态寄存器CPSR的影响

    • 指令中可以选择s后缀,以影响状态标志

      • 但是比较指令(CMP和CMN)和测试指令(TST和TEQ)不需要后缀S,它们总会直接影响CPSR中的状态标志
    • 关于恢复CPSR原值问题:

      • 如果指令带有S后缀(除了比较指令以外),同时又以PC为目标寄存器进行操作:

        • 在异常模式下:则操作的同时从SPSR恢复CPSR

        • 比如:

          movs pc, #0xff	/* cpsr = spsr; pc = 0xff */
          adds pc, r1, #0xff00/* cpsr = spsr; pc = r1 + 0xff00 */
          ands pc, r1, r2	/* cpsr = spsr; pc = r1 & r2; */
          
          • 在user或者system模式:会产生不可预料的结果,因为在这两种模式下没有SPSR
  5. 数据处理指令的详细列表(未含6条乘法指令)

    • 指令编码格式

      • opcode为数据处理指令操作码
      • I用于区别立即数(I为1)或寄存器移位(I为0)
      • S用于设置标志位
      • Rn为第一操作数寄存器,Rd为目标寄存器
      • operand2为第二个操作数,若指令不需要全部的可用操作数时(如MOV指令的Rn),不用的寄存器域应设置为0(由编译器自动完成)
      • 对于比较指令,b20位固定为1。
二、算术运算指令
  1. 加减运算指令

    • ADD——加法运算指令

      • 指令格式:ADD{cond}{S} Rd,Rn,operand2

      • ADD指令把第1源操作数寄存器Rn第2源操作数operand2相加后,将结果存放到目的寄存器 Rd

      • 执行流程(后面的指令,流程类似便不再列举了)

        • 举例:
          • ADD R0,R1,R2 ;R0←(R1)+(R2)
          • ADD R0,R1,#255 ;R0 ←(R1)+ 255
          • ADD R0,R2,R3,LSL#1 ;R0 ←(R2) +(R3<<1)
      • 受影响的CPSR标志位取值
        N寄存器Rd[31]被复制到N
        Z如果Rd为0,则Z=1,否则Z=0
        C运算结果有进位C=1,否则C=0
        V运算结果有溢出V=1,否则V=0
    • ADC——带进位加法指令

      • 指令格式:ADC{cond}{S} Rd,Rn,operand2
      • ADC指令将operand2的数据与Rn的值相加,再加上CPSR中的C条件标志位,结果保存到Rd寄存器。
      • 标志位只修改 N、Z、C、V这4个标志位
      • ADC通常用来实现字长大于32位的加法运算。
    • SUB——减法运算指令

      • 指令格式:SUB{cond}{S} Rd,Rn,operand2

      • SUB指令用寄存器Rn减去operand2,结果保存到Rd中

      • 受影响的CPSR标志位取值
        N寄存器Rd[31]被复制到N
        Z如果Rd为0则Z=1,否则Z=0
        C运算结果有借位则C=0,否则C=1
        V运算结果有溢出则V=1,否则V=0
    • SBC——带进位减法指令

      • 指令格式:SBC{cond}{S} Rd,Rn,operand2
      • SBC指令用寄存器Rn减去operand2,再减去CPSR中的C条件标志位的反码,结果保存到Rd中。
      • 标志位的修改同 SUB。
      • 该指令主要用于字长大于 32 位的数据的减法运算。
    • RSB——逆(反)向减法指令

      • 指令格式:RSB{cond}{S} Rd,Rn,operand2
      • RSB指令用operand2减去寄存器Rn,结果保存到Rd中。
    • RSC——带进位反向减法指令

      • 指令格式:RSC{cond}{S} Rd,Rn,operand2
      • RSC 指令用寄存器operand2减去Rn,再减去CPSR中的C条件标志位的反码,结果保存到Rd中。
  2. 乘法指令

    • ARM有两类乘法指令:

      • 32位的乘法指令,即乘法操作的结果为32位

      • 64位的乘法指令,即乘法操作的结果为64位

    • MUL——32位乘法指令

      • 指令格式:MUL{cond}{S} Rd,Rm,Rs

      • MUL指令将Rm和Rs中的值相乘,结果的低32位保存到Rd中(Rd ≠ Rm

      • 受影响的CPSR标志位取值
        N寄存器Rd[31]被复制到N
        Z如果Rd为0则Z=1,否则Z=0
    • MLA——32位乘加指令

      • 格式:MLA{cond}{S} Rd,Rm,Rs,Rn
      • 指令将Rm和Rs中的值相乘,再将乘积加上第3个操作数,结果的低32位保存到Rd中( Rd ≠ Rm )
      • 标志位的修改同 MUL
    • UMULL——64位无符号乘法指令

      • 指令格式:UMULL{cond}{S} RdLo,RdHi,Rm,Rs ; RdHi, RdLo← Rm*Rs

      • UMULL指令将Rm和Rs中的值作无符号数相乘,结果的低32位保存到RdLo中,高32位保存到RdHi中

      • 受影响的CPSR标志位取值
        N寄存器**RdHi[31]**被复制到N
        Z如果RdHi且Rdlo为0,则Z=1,否则Z=0
    • **UMLAL——64位无符号乘加指令 **

      • 指令格式:UMLAL{cond}{S} RdLo,RdHi,Rm,Rs ;RdHi, RdLo← Rm*Rs+ RdHi, RdLo
      • UMLAL指令将Rm和Rs中的值作无符号数相乘,64位乘积与RdHi、RdLo相加,结果的低32位保存到RdLo中,而高32位保存到RdHi中
      • 标志的修改同 UMULL
    • SMLAL—64位有符号乘加指令

      • 指令格式:SMLAL{cond}{S} RdLo,RdHi,Rm,Rs ; RdHi, RdLo← Rm*Rs+ RdHi, RdLo
      • SMLAL指令将Rm和Rs中的值作有符号数相乘64位乘积与RdHi、RdLo相加,结果的低32位保存到RdLo中,高32位保存到RdHi中
      • 标志的修改同 SMULL。
    • 乘法指令的特点

      • 不支持第2操作数为立即数
      • 结果寄存器不能与第一源寄存器相同
      • Rd、RdHi、RdLo不能与Rm为同一寄存器。
      • RdHi和RdLo不能为同一寄存器。
      • 避免将R15定义为任一操作数或结果寄存器
    • 乘法指令对标志位的影响

      • 对N标志位:
        • 若结果是32位指令形式,Rd的第31位是标志位N
        • 对于产生长结果的指令形式,RdHi的第31位是标志位N
      • 对Z标志位:如果Rd或RdHi、RdLo为0,则标志位Z置位
      • 对V标志位:乘法指令不影响V标志位
      • 对C标志位: ARM v5及以上的版本不影响C标志位; ARM v5以前的版本,C标志位数值不确定
    • 指令编码格式

      • opcode为乘法指令操作码
      • S为设置标志位
      • Rm为被乘数寄存器,Rs为乘数的寄存器
      • Rn/RdLo用于MLA指令相加的寄存器或64位乘法指令的目标寄存器(低32位)。
      • Rd/RdHi用于目标寄存器或64位乘法指令的目标寄存器(高32位)。
      • 若指令不需要全部的可用操作数时(如MUL指令的Rn),不用的寄存器域应设置为0(由编译器自动完成)。
三、逻辑运算指令(按位逻辑操作指令)
  • AND——逻辑“与”操作指令

    • 指令格式:AND{cond}{S} Rd,Rn,operand2

    • AND指令将operand2的值与寄存器Rn的值**按位逻辑“与”**操作,结果保存到Rd中。

    • 执行流程

    • 受影响的CPSR标志位取值
      N寄存器Rd[31]被复制到N
      Z如果Rd为0则Z=1,否则Z=0
      C不影响C标志位

      AND指令可用于提取寄存器中某些位的值,也可以用于把指定位清0

  • ORR——逻辑“或”操作指令

    • 指令格式: ORR{cond}{S} Rd,Rn,operand2
    • ORR指令将**operand2的值与寄存器Rn的值按位逻辑“或”**操作,结果保存到Rd中。
    • ORR指令用于将寄存器中某些位的值设置成1
    • 标志位的影响同AND。
  • EOR——逻辑“异或”操作指令

    • 指令格式:EOR{cond}{S} Rd,Rn,operand2
    • EOR指令将**operand2的值与寄存器Rn的值按位逻辑“异或”**操作,结果保存到Rd中。
    • EOR指令可用于将寄存器中某些位的值取反
      • 与0异或,该位值不变
      • 与1异或,该位值被求反
    • 标志位的影响同AND
  • BIC——位清除指令

    • 指令格式:BIC{cond}{S} Rd,Rn,operand2
    • BIC指令将寄存器Rn的值与operand2的值的反码按位逻辑**“与”**操作,结果保存到Rd中。
    • BIC指令可用于将寄存器中某些位的值清除为0
      • 将某一位 与1 做BIC操作,该位值被清除为0 ;
      • 将某一位 与0 做BIC操作,该位值不变。
四、数据传送指令
  1. MOV——数据传送指令

    • 指令格式:MOV{cond}{S} Rd,operand2

    • MOV指令将operand2传送到目标寄存器Rd中。

    • 受影响的CPSR标志位取值
      N寄存器Rd[31]被复制到N
      Z如果Rd为0,则Z=1,否则Z=0
      CC=0
    • 功能总结

      • 寄存器之间传送。
      • 立即数传送到寄存器中。(8位立即数位图)
      • 实现单纯的移位操作。MOV Rd,Rd,LSL,#3
      • 实现子程序调用、从子程序中返回。当PC寄存器作为目标寄存器时可以实现程序跳转。
      • 实现异常模式的返回,并把当前处理器模式的SPSR寄存器内容复制到CPSR中
        • 例:MOVS PC,LR ;PC←LR,异常模式下返回,且CPSR←SPSR
  2. MVN——数据求反传送指令

    • 指令格式:MVN{cond}{S} Rd,operand2
    • MVN指令将operand2按位取反后传送到目标寄存器Rd中。
五、比较指令
  1. CMP——比较指令

    • 指令格式:CMP{cond} Rn,operand2

    • CMP指令将寄存器Rn的值减去operand2的值,但不存储运算结果只根据操作的结果更新CPSR中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行。

    • 受影响的CPSR标志位取值
      N运算结果的第31位被复制到N
      Z运算结果为0则Z=1,否则Z=0
      C运算结果有借位则C=0,否则C=1
      V运算结果有溢出则V=1,否则V=0
    • 比较类指令本身带有更新 CPSR的功能,故在该指令中不能使用后缀 S

  2. CMN——负数比较指令

    • 指令格式:CMN{cond} Rn,operand2
    • CMN指令将寄存器Rn的值减去operand2的负数(即加上operand2的值),但不存储运算结果,只根据操作的结果更新CPSR中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行。
六、测试指令
  1. TST——位测试指令
    • 指令格式:TST{cond} Rn,operand2
    • TST指令将寄存器Rn的值与operand2的值按位逻辑“与”操作,但不存储运算结果,只根据操作的结果更新CPSR中的相应条件标志位
    • 该指令一般用来检测是否设置了特定的位
  2. TEQ——测试相等指令
    • 指令格式:TEQ{cond} Rn,operand2
    • TEQ指令将寄存器Rn的值与operand2的值**按位逻辑“异或”**操作,但不存储运算结果,只根据操作的结果更新CPSR中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行。
      • 例子:
        • TEQ R0,R1
        • ;比较R0与R1是否相等
        • ;(不影响V位和C位)

3.3.3 存储器访问指令

  • ARM微处理器用加载/存储指令访问存储器,实现在寄存器和存储器之间传送数据。
  • 由于ARM处理器对外设寄存器、I/O映射空间与存储器统一编址,因此,对外围设备的I/O操作也用此类指令
  • 基本的加载/存储指令仅有5条,分为3种:
    • LDR和STR,单寄存器加载/存储指令
    • LDM和STM,多寄存器加载/存储指令
    • SWP,寄存器和存储器数据交换指令
一、 单寄存器的存取指令
  • 单寄存器加载/存储指令是ARM在寄存器和存储器间传送单个字节和字的最灵活方式。
  • 根据传送数据的类型不同,单个寄存器存取指令又可以分为以下两类:
    • 单字和无符号字节的加载/存储指令
    • 半字和有符号字节的加载/存储指令
  1. 单字和无符号字节的加载/存储指令

    • LDR:指令从内存中取32位字或8位无符号字节数据放入寄存器

      • 内存到寄存器
    • STR:指令将寄存器中的32位字或8位无符号字节数据保存到存储器中。

      • 寄存器到内存
    • 注意:无符号字节加载时,用0将8位的操作数扩展到32位

    • 指令格式

      • LDR{cond}{T} Rd,<地址> ;加载指定地址上的字数据,放入Rd中。
      • STR{cond}{T} Rd,<地址> ;存储Rd中字数据,到指定地址的存储单元。
      • LDR{cond}B{T} Rd,<地址> ;加载字节数据到Rd低8位数据位中,高24位为0
      • STR{cond}B{T} Rd,<地址> ;存储Rd中字节数据, Rd中最低字节为传送数据
      • T后缀
        • T为可选后缀,若指令有T,存储系统将访问看成是处理器在用户模式下。
        • 用于存储器保护。
        • 不能与后变址模式、自动变址模式一起使用(即不能改变基址寄存器值)。
        • T在用户模式下无效。
    • 操作数寻址方式

      • LDR/STR指令为基址变址寻址(或寄存器间接寻址),由两部分组成:

        • 基地址部分:为一个基址寄存器,可以为任一个通用寄存器

        • 偏移地址部分:这一部分非常灵活,实际就类似第二个操作数,可以有以下3种格式:

          • 立即数:12位立即数是一个无符号的数值。这个数据可以加到基址寄存器,也可以从基址寄存器中减去这个数值。

            • 指令举例如下:

              LDR    R1,[R0,#0x10]      ;将R0+0x10地址处的数据读出,			;保存到R1中(R0的值不变)       
              LDR    R1,[R0,# -0x10]       			;将R0-0x10地址处的数据读出,			;保存到R1中(R0的值不变)
              
          • 寄存器:寄存器中的数值(无符号数)可以加到基址寄存器,也可以从基址寄存器中减去这个数值。

            • 指令举例如下:

              LDR    R1,[R0,R2] ;将R0+R2地址处的数据读出,保存到R1中
              LDR    R1,[R0,-R2] ;将R0-R2地址处的数据读出,保存到R1中
              
          • 寄存器及移位常数:寄存器移位后的值(无符号数)可以加到基址寄存器,也可以从基址寄存器中减去这个数值。

            • 指令举例如下:

              LDR    R1,[R0,R2,LSL #2];将R0+R2×4地址处的数据读出,;保存到R1中(R0、R2的值不变)
              LDR    R1,[R0,-R2,LSL #2];将R0-R2×4地址处的数据读出,;保存到R1中(R0、R2的值不变)
              
              • 注意:移位位数只能是5位的立即数,不能使用寄存器指定移位位数
    • 指令编码格式

  2. 半字和有符号字节的加载/存储指令

    • 这类LDR/STR指令可实现半字(有符号和无符号)、有符号字节数据的传送。

    • 特点:

      • 偏移量格式、寻址方式与加载/存储字和无符号字节指令基本相同
      • 立即数偏移量限定在8位
      • 寄存器偏移量不可经过移位得到。
    • 指令格式

      • LDR {cond}SB Rd,<地址> ;加载指定地址上有符号字节到Rd中,高24位用符号位扩展
      • LDR {cond}SH Rd,<地址> ;加载指定地址上的有符号半字到Rd中,高16位用符号位扩展
      • LDR {cond}H Rd,<地址> ;加载无符号半字数据到Rd的低16位,高16位清零
      • STR{cond}H Rd,<地址> ;存储Rd中的低16位半字数据
    • 两点说明:

      • 符号位
        • 有符号字节或有符号半字的加载,用**“符号位”扩展到32位**
        • 无符号半字传送是用0扩展到32位
      • 地址对齐
        • 对半字传送的地址必须为偶数。非半字对齐的半字加载将使Rd内容不可靠
        • 非半字对齐的半字存储将使指定地址的2字节存储内容不可靠。
    • 指令编码格式

  • 看PPT的例子P127-130
二、多寄存器的存取指令
  • LDM和STM指令可以实现在一组寄存器一块连续的内存单元之间存/取数据。

    • LDM为加载多个寄存器(内存到寄存器
    • STM为存储多个寄存器(**寄存器到内存)
  • 这两条指令,允许传送16个寄存器R0—R15的任何子集或所有寄存器。

  • 指令格式

    • LDM{cond}<模式> Rn{!},<reglist>{^}
    • STM{cond} <模式> Rn{!},<reglist>{^}
    • 指令格式说明
      • Rn:表示基址寄存器,装有传送数据的初始地址,Rn不允许为R15(即PC)
      • Rn后缀 **“!” **:表示最后的地址写回到Rn中
      • reglist:表示寄存器列表,其中包含一个或多个寄存器。当寄存器不连续时,中间使用“,”隔开。
        • 格式例子:{R1,R2,R6-R9}
        • 列表寄存器和存储器地址的关系规则:编号低的寄存器对应于存储器中低地址单元,编号高的寄存器对应于存储器中高地址单元
    • 后缀 “^” 说明
      • 寄存器列表不包含PC
        • 使用后缀“^”进行数据传送时,加载/存储的是用户模式的寄存器,而不是当前模式的寄存器
      • 寄存器列表包含有PC
        • 除了正常的多寄存器传送外,还要将SPSR拷贝到CPSR中。该用法可用于异常处理返回
      • 禁用情况:后缀“^”不允许在用户模式或系统模式下使用。 因为它们没有SPSR
    • Rn在寄存器列表中且使用后缀“!”
      • 对于STM指令,若Rn为寄存器列表中的最低序号的寄存器,则会将Rn的初值保存;
      • 其它情况下Rn的编译无法通过。
    • 地址字对齐:这些指令寻址是字对齐的,即忽略地址位[1:0]。
  • 指令编码格式

  • 模式项

    • LDM/STM的主要用途是现场保护、数据复制和参数传送等。

    • 其模式有如下8种(前面4种用于数据块的传输(为存储操作), 后面4种是堆栈操作):

      类型每次基址寄存器的操作传送起始地址Rn序号的变化
      IA先传送数据,后基地址加4(Rn)增加
      IB先基地址加4,后传送数据(Rn)+4增加
      DA先传送数据,后基地址减4(Rn)减少
      DB先基地址减4,后传送数据(Rn)-4减少
      类型堆栈类型弹出(pop)指令压入(push)指令
      FA递增满堆栈LDMFASTMFA
      FD递减满堆栈LDMFDSTMFD
      EA递增空堆栈LDMEASTMEA
      ED递减空堆栈LDMEDSTMED
      • 堆栈操作与批量传输对应

        寻址方式说明pop=LDMpush=STM
        FA递增满LDMFALDMDASTMFASTMIB
        FD递减满LDMFDLDMIASTMFDSTMDB
        EA递增空LDMEALDMDBSTMEASTMIA
        ED递减空LDMEDLDMIBSTMEDSTMDA
  • 示例

    • 这里能看出来序号高的寄存器一定会存/取地址高的地址
三、单寄存器交换指令(SWP)
  • SWP指令用于将一个存储单元(该单元地址放在寄存器Rn中)的内容读取到一个寄存器Rd中,同时将另一个寄存器Rm的内容写入到该存储单元中

  • 交换指令是一个原子操作,也就是说,在连续的总线操作中读/写一个存储单元,在操作期间阻止其它任何指令对该存储单元的读写

  • 指令格式

    • SWP{cond}{B} Rd,Rm,[Rn]
    • B为可选后缀,若有B,则交换无符号字节,否则交换32位字
    • Rd为被加载的寄存器
    • Rm的数据用于存储到Rn所指的地址中,若Rm与Rd相同,则为寄存器与存储器内容进行交换
    • Rn为要进行数据交换的存储器地址,Rn不能与Rd和Rm相同。
    • 功能:将一个内存单元[Rn]的内容读取到一个寄存器Rd中,同时将另一个寄存器Rm的内容写入到该内存单元中
  • 指令编码格式

  • 指令举例

    • SWP R1,R1,[R0];将R1的内容与R0指向的存储单元的内容进行交换。
    • SWPB R1,R2,[R0];将R0指向的存储单元的内容读取1字节数据到R1中(高24位清零),并将R2的内容写入到该内存单元中(最低字节有效)
3.3.5 杂项指令
  • 主要由两种类型指令组成,程序状态寄存器操作指令、中断操作指令,一共有5条指令。
    • 状态寄存器操作指令:
      • MRS:读程序状态寄存器指令
      • MSR:写程序状态寄存器指令
    • 异常中断操作指令:
      • SWI: 软件中断指令
      • BKPT:断点指令(v5T体系)
      • CLZ: 前导0计数(v5T体系)
一、程序状态寄存器处理指令
  • ARM指令中有两条指令,用于在状态寄存器通用寄存器之间传送数据。修改状态寄存器一般是通过“读取-修改-写回”三个步骤的操作来实现的。
  1. MRS–读状态寄存器指令

    • 指令格式:MRS{cond} Rd,psr ; Rd <- psr

    • 把**状态寄存器psr(CPSR或SPSR)**的内容传送到目标寄存器中。

      • Rd —— 目标寄存器。Rd不允许为R15。
      • psr —— CPSR或SPSR。
    • 指令编码格式

      • 注意:在ARM处理器中,只有MRS指令可以将状态寄存器CPSR或SPSR读出到通用寄存器中。
  2. MSR–写状态寄存器指令

    • 在ARM处理器中,只有MSR指令可以直接设置状态寄存器CPSR或SPSR

    • 指令格式如下:

      • MSR{cond} psr_fields,#immed

      • MSR{cond} psr_fields,Rm

      • 其中:

        • psr:CPSR或SPSR

        • immed:要传送到状态寄存器指定域的8位立即数

        • Rm:要传送到状态寄存器指定域的数据的源寄存器

        • fields:指定传送的区域。fields可以是以下的一种或多种:

          • c 控制域 (psr[7…0]);

          • x 扩展域(psr[15…8]);(暂未用)

          • s 状态域 (psr[23…16]);(暂未用)

          • f 标志位域 (psr[31…24])。

    • 指令举例

      • MSR CPSR_cxsf,R0 ;传送R0的内容到CPSR
      • MSR SPSR_cxsf,R0 ;传送R0的内容到SPSR
      • MSR CPSR_c,R0 ;传送R0的内容到CPSR,但仅仅修改CPSR中的控制位域
      • MSR CPSR_cfxs,R0 ;传送R0的内容到CPSR,修改所有域
    • 注 意:

      • 控制域的修改问题:只有在特权模式下才能修改状态寄存器的控制域[7:0],以实现处理器模式转换,或设置开/关异常中断 。
      • T控制位的修改问题:程序中不能通过MSR指令,直接修改CPSR中的T控制位来实现ARM状态/Thumb状态的切换,必须使用BX指令完成处理器状态的切换
      • 用户模式下能够修改的位:在用户模式只能修改“标志位域”,不能对CPSR[23:0]做修改。
      • S后缀的使用问题:在MRS/MSR指令中不可以使用S后缀
二、异常中断产生指令
  • 异常中断指令可以分为以下几种:
    • SWI: 软件中断指令
    • BKPT:断点指令(v5T及以上体系)
    • CLZ: 前导0计数(v5T及以上体系)
  1. SWI——软件中断指令

    • 软件中断指令SWI产生软件异常中断,用来实现用户模式到特权模式的切换

    • 用于在用户模式下对操作系统中特权模式的程序的调用;

    • 它将处理器置于管理(svc)模式,中断矢量地址为0x08。

    • 指令格式如下:SWI {<cond>} <24位立即数>

      • 24位立即数,指定用户程序调用系统例程的类型,相关参数通过寄存器传递,当指令中24位立即数被忽略时(立即数为0),用户程序调用系统例程的类型由通用寄存器R0决定,同时参数通过其它寄存器传递
    • 指令编码格式

    • 说明:

      • 主要用于用户程序调用操作系统的API。
      • 参数传递通常有两种方法:
        • 指令中的24bit立即数指定API号,其它参数通过寄存器传递。
        • 忽略指令中的24bit立即数,r0指定API号,其它参数通过其它寄存器传递。
    • 举例

      • 软中断号在指令中,不传递其它参数:
        • SWI 10 ;中断类型号为10(注:没有#号)
        • SWI 0x123456 ;中断类型号为0x123456
      • 软中断号在指令中,其它参数在寄存器中传递:
        • MOV R0,#34 ;准备参数
        • SWI 12 ;调用12号软中断
      • 不用指令中的立即数,软中断类型号和其它参数都在寄存器中传递:
        • MOV R0,#12 ;准备中断类型号
        • MOV R1,#34 ;准备参数
        • SWI 0 ;进入软中断。
  2. BKPT——断点指令(了解)

    • 断点中断指令BKPT用于产生软件断点,供调试程序用。
    • v5T及以上体系使用。
    • 指令格式如下: BKPT { immed_16}
      • immed_16:16位的立即数。该立即数被调试软件用来保存额外的断点信息。
    • 断点指令用于软件调试;它使处理器停止执行正常指令而进入相应的调试程序。
  3. CLZ——前导0计数指令(了解)

    • 前导0计数指令CLZ 对Rm中的前导0的个数进行计数,结果放到Rd中。

    • v5T及以上体系使用。

    • 指令格式:CLZ{<cond>} Rd, Rm

    • 举例如下:

       MOV   R2, #0X17C00 ;R2=0b0000 0000 0000 0001 0111 1100 0000 0000      CLZ   R3, R2    		;R3=15
      

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

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

相关文章

Spring Boot接口通用返回值设计与实现最佳实践

一、核心返回值模型设计&#xff08;增强版&#xff09; package com.chat.common;import com.chat.util.I18nUtil; import com.chat.util.TraceUtil; import lombok.AllArgsConstructor; import lombok.Data; import lombok.Getter;import java.io.Serializable;/*** 功能: 通…

2025年上半年软件架构师考试回忆版【持续更新】

文章目录 案例分析1、端AI相对于云AI的优势2、redis持久化&#xff0c;主从库3、解释器架构风格4、知识图谱5、区块链 论文1、基于事件驱动的模型2、多模型数据库及其应用3、负载均衡设计方法4、论软件测试理论及其应用 考试感受 2025年软件考试架构考试于5月24日如期举行&…

Windows下编译Zipios

本文记录在Windows下编译Zipios的流程。 注1&#xff1a;文章内容会不定期更新。 零、环境 操作系统Windows 11VS Code1.92.1Git2.34.1Visual StudioVisual Studio Community 2022CMake3.22.1 一、安装依赖 二、编译 2.1 下载代码 git clone https://github.com/Zipios/Zi…

SOC-ESP32S3部分:11-任务创建

飞书文档https://x509p6c8to.feishu.cn/wiki/EH3owsPahisvl6kL6k3cqaQ3n0g 在我们学习单片机的时候&#xff0c;main函数入口中一般有一个while大循环在不停轮询&#xff0c;如果我们需要实现多种不同的业务&#xff0c;就需要用到状态机&#xff0c;根据不同时刻的要求执行不…

[Git] 如何进行版本回退

版本控制系统最重要的能力之一&#xff0c;就是能够轻松地在项目的不同历史版本之间切换。有时&#xff0c;你可能发现最近的修改引入了严重问题&#xff0c;或者需要回到之前的某个节点重新开始。这时&#xff0c;“版本回退”功能就派上用场了。 版本回退&#xff1a;反方向…

易贝平台关键字搜索技术深度解析

一、核心搜索机制 关键词匹配原理 采用TF-IDF算法计算关键词权重 支持同义词扩展&#xff08;如"phone"匹配"cellphone"&#xff09; 标题权重 > 副标题 > 商品描述 搜索排序因素 # 搜索权重模拟计算 def calculate_rank(keyword, item): title…

深度剖析 MCP SDK 最新版:Streamable HTTP 模式

好记忆不如烂笔头&#xff0c;能记下点东西&#xff0c;就记下点&#xff0c;有时间拿出来看看&#xff0c;也会发觉不一样的感受. 目录 一、概述 二、快速上手&#xff1a;开启 Streamable HTTP 服务端开启 客户端连接 三、深入两个核心参数 stateless_http json_resp…

树莓派开箱上手教程(无需显示器版)

树莓派开箱上手教程&#xff08;无需显示器版&#xff09; 硬件准备 名称参数电源适配器5V电源适配器&#xff0c;至少需要3A的额定电流&#xff0c;配备USB Type-C输出接头microSD卡用来将树莓派的操作系统安装到上边&#xff0c;至少需要8GB容量&#xff0c;一般建议16GB及以…

MySQL强化关键_015_存储过程

目 录 一、概述 1.说明 2.优点 3.缺点 二、存储过程的操作 1.创建 2.调用 3.查看 4.删除 三、变量 1.系统变量 &#xff08;1&#xff09;说明 &#xff08;2&#xff09;查看系统变量 &#xff08;3&#xff09;设置系统变量 2.用户变量 &#xff08;1&…

动态规划dp

这里写目录标题 动态规划01背包完全背包多重背包混合背包二维费用的背包分组背包有依赖的背包背包问题求方案数背包问题求具体方案数位 DP状压 DP常用例题 动态规划 01背包 有 n n n 件物品和一个容量为 W W W 的背包&#xff0c;第 i i i 件物品的体积为 w [ i ] w[i] w…

arcgis js统计FeatureLayer的椭球面积、平面面积

1、导入依赖 import FeatureLayer from arcgis/core/layers/FeatureLayer import { geodesicArea, planarArea, simplify } from arcgis/core/geometry/geometryEngine; import { project, load as projectionLoad } from arcgis/core/geometry/projection2、初始化project o…

2.2.1 05年T2

引言 本文将从一预习、二自习、三学习、四复习等四个阶段来分析2005年考研英语阅读第二篇文章。为了便于后续阅读&#xff0c;我将第四部分复习放在了首位。 四、复习 方法&#xff1a;错误思路分析总结考点文章梳理 4.1 错题分析 题目&#xff1a;26&#xff08;细节题&…

Java 连接并操作 Redis 万字详解:从 Jedis 直连到 RedisTemplate 封装,5 种方式全解析

引言 在分布式系统和高并发场景中&#xff0c;Redis 作为高性能内存数据库的地位举足轻重。对于 Java 开发者而言&#xff0c;掌握 Redis 的连接与操作是进阶必备技能。然而&#xff0c;从基础的 Jedis 原生客户端到 Spring 封装的 RedisTemplate&#xff0c;不同连接方式的原…

谈谈对《加密算法》的理解

文章目录 一、什么是加密算法&#xff1f;二、常见的加密算法有哪些&#xff1f;2.1 对称加密2.2 非对称加密2.3 哈希算法 三、加密算法代码展示3.1 MD5加密3.2 秘钥加密3.3 AES加密解密 四、加密算法的使用场景 一、什么是加密算法&#xff1f; 加密算法是一种通过数学方法将…

Fuzz 模糊测试篇JS 算法口令隐藏参数盲 Payload未知文件目录

1 、 Fuzz 是一种基于黑盒的自动化软件模糊测试技术 , 简单的说一种懒惰且暴力的技术融合了常见 的以及精心构建的数据文本进行网站、软件安全性测试。 2 、 Fuzz 的核心思想 : 口令 Fuzz( 弱口令 ) 目录 Fuzz( 漏洞点 ) 参数 Fuzz( 利用参数 ) PayloadFuzz(Bypass)…

哈希表的实现(下)

目录 前言 开散列概念 开散列实现 Insert 优化 Find Erase 前言 上一章节我们用闭散列实现了一下哈希表&#xff0c;但存在一些问题&#xff0c;比如空间浪费比较严重&#xff0c;如果连续一段空间都已经存放值&#xff0c;那么在此位置插入新值的时候就会一直挪动&…

再谈Linux 进程:进程等待、进程替换与环境变量

目录 1.进程等待 为什么需要进程等待&#xff1f; 相关系统调用&#xff1a;wait()和waitpid() wait(): waitpid(): 解析子进程状态&#xff08;status&#xff09; 2.进程替换 为什么需要进程替换&#xff1f; 相关系统调用&#xff1a;exec函数家族 3.环境变量 ​…

基于深度学习的无线电调制识别系统

基于深度学习的无线电调制识别系统 本项目实现了一个基于深度学习的无线电调制识别系统&#xff0c;使用LSTM&#xff08;长短期记忆网络&#xff09;模型对不同类型的 无线电信号进行自动分类识别。该系统能够在不同信噪比(SNR)条件下&#xff0c;准确识别多种调制类型&#…

Python 爬虫之requests 模块的应用

requests 是用 python 语言编写的一个开源的HTTP库&#xff0c;可以通过 requests 库编写 python 代码发送网络请求&#xff0c;其简单易用&#xff0c;是编写爬虫程序时必知必会的一个模块。 requests 模块的作用 发送网络请求&#xff0c;获取响应数据。 中文文档&#xf…

随机森林(Random Forest)学习

随机森林是一种基于集成学习的机器学习算法&#xff0c;属于Bagging&#xff08;Bootstrap Aggregating&#xff09;方法的一种扩展。它通过组合多个决策树来提升模型的泛化能力和鲁棒性&#xff0c;广泛用于分类、回归和特征选择任务。 1.随机森林核心思想 1.1少数服从多数 在…