2025年ldr arm指令(arm lsl指令)

ldr arm指令(arm lsl指令)汇编 指令是 CPU 机器指令的助记符 经过编译后会得到一串 10 组成的机器码 可以由 CPU 读取执行 汇编 伪指令本质上不是指令 只是和指令一起写在代码中 它是编译器环境提供的 目的是用来指导编译过程 经过编译后伪指令最终不会生成机器码 ARM 官方的 ARM 汇编风格 指令一般用大写



(汇编)指令是CPU机器指令的助记符,经过编译后会得到一串10组成的机器码,可以由CPU读取执行。

(汇编)伪指令本质上不是指令(只是和指令一起写在代码中),它是编译器环境提供的,目的是用来指导编译过程,经过编译后伪指令最终不会生成机器码。

ARM官方的ARM汇编风格:指令一般用大写、Windows中IDE开发环境(如ADS、MDK等)常用。如: LDR R0, [R1]

GNU风格的ARM汇编:指令一般用小写字母、linux中常用。如:ldr r0, [r1]

ARM官方已经确认采用GNU风格的ARM汇编作为其官方推荐的风格。这意味着在将来的ARM开发中,建议使用小写字母的指令格式,例如"ldr r0, [r1]"。

  • ARM采用RISC架构,CPU本身不能直接读取内存,而需要先将内存中内容加载入CPU中通用寄存器中才能被CPU处理。
  • LDR指令(Load Register)用于将内存中的数据加载到寄存器中。
  • STR指令(Store Register)用于将寄存器中的数据存储到内存中。
  • LDR/STR组合用来实现 ARM CPU和内存数据交换

1、寄存器寻址                    mov r1, r2            (将 r2 寄存器的值复制到 r1 寄存器中

2、立即寻址                       mov r0, #0xFF00  (将常数 0xFF00 加载到 r0寄存器 中

3、寄存器移位寻址            mov r0, r1, lsl #3   (将 r1 的值左移 3 位,然后将结果存入 r0 中

LSL:逻辑左移,移位后寄存器空出的低位补0。
LSR:逻辑右移,移位后寄存器空出的高位补0。
ASR:算术右移,移位过程中,符号位保持不变,如果源操作数是正数,则空出的高位补0,否则补1.
ROR:循环右移,移位后移除的低位填入空出的高位。
RRX:带扩展的循环右移,操作数右移一位,移位空出的高位用C标志的值填充。

4、寄存器间接寻址            ldr r1, [r2]              (从内存中读取 r2 的数据,并存入 r1 中

5、基址变址寻址               ldr r1, [r2, #4]    (将 r2 作为基址,再加上偏移量 4,从相应的内存地址读取数据并存入 r1 中;r2+4地址的数据存入r1

6、多寄存器寻址               ldmia r1!, {r2-r7, r12}   (将 r1 指向的内存地址开始的一段连续的数据加载到 r2-r7 和 r12 这些寄存器中;r1相当于数组8个元素依次读入到8个寄存器)

7、堆栈寻址                      stmfd sp!, {r2-r7, lr}  (将 r2-r7 和 lr 这些寄存器的值依次保存到堆栈中,同时堆栈指针 sp 会自动减小

8、相对寻址                      beq flag   (根据指令跳转的相对位置来确定目标地址,通常用于分支指令。例如, 表示如果前一个指令的比较结果为相等,则跳转到标记为 flag 的位置继续执行。

同一指令经常附带不同后缀,变成不同的指令。经常使用的后缀有:
B(byte)功能不变,操作长度变为8位
H(half word)功能不变,长度变为16位
S(signed)功能不变,操作数变为有符号
如 ldr ldrb ldrh ldrsb ldrsh
S(S标志)功能不变,影响CPSR标志位
如 mov和movs  movs r0, #0

根据进行条件判断

条件执行后缀用于在指令执行之前设置条件,只有在满足条件的情况下指令才会被执行。条件执行后缀可以使得指令的执行更加灵活和有选择性,根据特定条件来决定是否执行某个指令或者跳转。

为增加处理器指令流的速度, ARM 使用多级流水线 . ,下图为3级流水线工作原理示意图。(S5PV210使用13级流水线,ARM11为8级)
允许多个操作同时处理,而非顺序执行。

PC 指向正被取指的指令,而非正在执行的指令
程序中断返回时需要注意,返回地址要回退
•数据传输指令  mov mvn
•算术指令         add sub rsb adc sbc rsc
•逻辑指令         and orr eor bic
•比较指令         cmp cmn tst teq
•乘法指令         mvl mla umull umlal smull smlal

        •前导零计数     clz

这些指令的作用是在计算机中对数据进行处理,进行各种运算或传输操作

  • mrs & msr
mrs用来读psr,msr用来写psr
CPSR寄存器比较特殊,需要专门的指令访问,这就是mrs和msr。
  • b & bl & bx
  • b 直接跳转(就没打开算返回)
  • bl branch and link,跳转前把返回地址放入lr中,以便返回,以便用于函数调用
  • bx跳转同时切换到ARM模式,一般用于异常处理的跳转。
  • ldr/str &  ldm/stm & swp
  • 单个字/半字/字节访问 ldr/str
  • 多字批量访问  ldm/stm
  • swp r1, r2, [r0]

ARM汇编中的立即数

合法立即数与非法立即数
  • ARM指令都是32位,除了指令标记和操作标记外,本身只能附带很少位数的立即数。因此立即数有合法和非法之分。
  • 合法立即数:经过任意位数的移位后非零部分可以用8位表示的即为合法立即数
  • 非法立即数则是不满足合法立即数条件的立即数。
  • swi(software interrupt)
软中断指令用来实现操作系统中系统调用,它提供了一种机制,让用户程序与操作系统进行交互,实现了用户程序与底层硬件的隔离和保护。(写操作系统用)
  • mcr & mrc
  • mrc用于读取CP15中的寄存器
  • mcr用于写入CP15中的寄存器

协处理器

SoC内部另一处理核心,协助主CPU实现某些功能,被主CPU调用执行一定任务。

  • ARM设计上支持多达16个协处理器,但是一般SoC只实现其中的CP15.(cp:coprocessor)
  • 协处理器和MMU、cache、TLB等处理有关,功能上和操作系统的虚拟地址映射、cache管理等有关。

MRC & MCR的使用方法

  • mcr{<cond>}   p15, <opcode_1>, <Rd>, <Crn>, <Crm>, {<opcode_2>}
  • opcode_1:对于cp15永远为0
  • Rd:           ARM的普通寄存器
  • Crn:          cp15的寄存器,合法值是c0~c15
  • Crm:         cp15的寄存器,一般均设为c0
  • opcode_2:一般省略或为0

ldm/stm与栈的处理

为什么需要多寄存器访问指令

  • ldr/str每周期只能访问4字节内存,如果需要批量读取、写入内存时太慢,解决方案是stm/ldm
  • ldm(load register mutiple)
  • stm(store register mutiple)
批量读取或写入内存时要用ldm/stm指令

8种后缀

  • ia(increase after)先传输,再地址+4
  • ib(increase before)先地址+4,再传输
  • da(decrease after)先传输,再地址-4
  • db(decrease before)先地址-4,再传输
  • fd(full decrease)满递减堆栈
  • ed(empty decrease)空递减堆栈
  • fa(·······) 满递增堆栈
  • ea(·······)空递增堆栈
例:stmia  sp, {r0 - r12}
  • 将r0存入sp指向的内存处(假设为0x30001000);然后地址+4(即指向0x30001004),将r1存入该地址;然后地址再+4(指向0x30001008),将r2存入该地址······直到r12内容放入(0x3001030),指令完成。
  • 一个访存周期同时完成13个寄存器的读写
最常见的是stmia和stmfd

四种栈

  • 空栈:栈指针指向空位,每次存入时可以直接存入然后栈指针移动一格;而取出时需要先移动一格才能取出
  • 满栈:栈指针指向栈中最后一格数据,每次存入时需要先移动栈指针一格再存入;取出时可以直接取出,然后再移动栈指针
  • 增栈:栈指针移动时向地址增加的方向移动的栈
  • 减栈:栈指针移动时向地址减小的方向移动的栈
操作栈时使用相同的后缀就不会出错,不管是满栈还是空栈、增栈还是减栈

!的作用

  • ldmia  r0, {r2 - r3}
  • ldmia  r0!, {r2 - r3}

感叹号的作用就是r0的值在ldm过程中发生的增加或者减少最后写回到r0去,也就是说ldm时会改变r0的值。

^的作用

ldmfd  sp!, {r0 - r6, pc}

ldmfd  sp!, {r0 - r6, pc}^

^的作用:在目标寄存器中有pc时,会同时将spsr写入到cpsr,一般用于从异常模式返回。

  • 伪指令不是指令,伪指令和指令的根本区别是经过编译后会不会生成机器码
  • 伪指令的意义在于指导编译过程。
  • 伪指令是和具体的编译器相关的,我们使用gnu工具链,因此学习gnu环境下的汇编伪指令。
  • .global _start  @ 给_start外部链接属性
  • .section .text  @ 指定当前段为代码段
  • .ascii .byte .short .long .word
  • .quad .float .string @ 定义数据
  • .align 4  @ 以16字节对齐
  • .balignl 16 0xabcdefgh   @ 16字节对齐填充
  • .end  @标识文件结束
  • .include  @ 头文件包含
  • .arm / .code32  @声明以下为arm指令
  • .thumb / .code16  @声明以下为thubm指令
  • ldr  大范围的地址加载指令
  • adr  小范围的地址加载指令
  • adrl  中等范围的地址加载指令
  • nop  空操作
  • ARM中有一个ldr指令,还有一个ldr伪指令
  • 一般都使用ldr伪指令而不用ldr指令

adr与ldr区别

  • adr编译时会被1条sub或add指令替代,而ldr编译时会被一条mov指令替代或者文字池方式处理
  • adr总是以PC为基准来表示地址,因此指令本身和运行地址有关,可以用来检测程序当前的运行地址在哪里
  • ldr加载的地址和链接时给定的地址有关,由链接脚本决定。
  • ldr加载的地址在链接时确定,而adr加载的地址在运行时确定
  • @ 用来做注释。可以在行首也可以在代码后面同一行直接跟,和C语言中//类似
  • # 做注释,一般放在行首,表示这一行都是注释而不是代码。
  • :以冒号结尾的是标号
  • .  点号在gnu汇编中表示当前指令的地址
  • # 立即数前面要加#或$,表示这是个立即数

编程小号
上一篇 2025-03-08 07:21
下一篇 2025-02-11 14:01

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ri-ji/39973.html