【汇编指令】一些基础的汇编指令

风流意气都作罢 提交于 2019-12-16 11:08:28

汇编

ARM的六大类指令集—LDR、LDRB、LDRH、STR、STRB、STRH

— LDR 字数据加载指令— LDRB 字节数据加载指令— LDRH 半字数据加载指令— STR 字数据存储指令— STRB 字节数据存储指令— STRH 半字数据存储指令

LDR指令LDR指令的格式为:

LDR{条件} 目的寄存器,<存储器地址>
LDR指令用于从存储器中将一个32位的字数据传送到目的寄存器中。该指令通常用于从存储器中读取32位的字数据到通用寄存器,然后对数据进行处理。当程序计数器PC作为目的寄存器时,指令从存储器中读取的字数据被当作目的地址,从而可以实现程序流程的跳转。
指令示例:

  • LDR R0,[R1];
    将存储器地址为R1的字数据读入寄存器R0。
  • LDR R0,[R1,R2] ;
    将存储器地址为R1+R2的字数据读入寄存器R0。
  • LDR R0,[R1,#8];
    将存储器地址为R1+8的字数据读入寄存器R0。
  • LDR R0,[R1,R2] ! ;
    将存储器地址为R1+R2的字数据读入寄存器R0,并将新地址R1+R2写入R1。
  • LDR R0,[R1,#8] !;
    将存储器地址为R1+8的字数据读入寄存器R0,并将新地址R1+8写入R1。
  • LDR R0,[R1],R2 ;
    将存储器地址为R1的字数据读入寄存器R0,并将新地址R1+R2写入R1。
  • LDR R0,[R1,R2,LSL#2]! ;
    将存储器地址为R1+R2×4的字数据读入寄存器R0,并将新地址R1+R2×4写入R1。
  • LDR R0,[R1],R2,LSL#2 ;
    将存储器地址为R1的字数据读入寄存器R0,并将新地址R1+R2×4写入R1。
LDRB指令

LDRB指令的格式为:LDR{条件}B 目的寄存器,<存储器地址>
LDRB指令用于从存储器中将一个8位的字节数据传送到目的寄存器中,同时将寄存器的高24位清零。该指令通常用于从存储器中读取8位的字节数据到通用寄存器,然后对数据进行处理。当程序计数器PC作为目的寄存器时,指令从存储器中读取的字数据被当作目的地址,从而可以实现程序流程的跳转。
指令示例:

  • LDRB R0,[R1] ;
    将存储器地址为R1的字节数据读入寄存器R0,并将R0的高24位清零。
  • LDRB R0,[R1,#8] ;
    将存储器地址为R1+8的字节数据读入寄存器R0,并将R0的高24位清零。
LDRH指令

LDRH指令的格式为:LDR{条件}H 目的寄存器,<存储器地址>
LDRH指令用于从存储器中将一个16位的半字数据传送到目的寄存器中,同时将寄存器的高16位清零。该指令通常用于从存储器中读取16位的半字数据到通用寄存器,然后对数据进行处理。当程序计数器PC作为目的寄存器时,指令从存储器中读取的字数据被当作目的地址,从而可以实现程序流程的跳转。
指令示例:

  • LDRH R0,[R1] ;
    将存储器地址为R1的半字数据读入寄存器R0,并将R0的高16位清零。
  • LDRH R0,[R1,#8] ;
    将存储器地址为R1+8的半字数据读入寄存器R0,并将R0的高16位清零。
  • LDRH R0,[R1,R2] ;
    将存储器地址为R1+R2的半字数据读入寄存器R0,并将R0的高16位清零。
LDM指令:

L的含义仍然是LOAD,即是Load from memory into register。虽然貌似是LDR的升级,但是,千万要注意,这个指令运行的方向和LDR是不一样的,是从左到右运行的。该指令是将内存中堆栈内的数据,批量的赋值给寄存器,即是出栈操作;其中堆栈指针一般对应于SP,注意SP是寄存器R13,实际用到的却是R13中的内存地址,只是该指令没有写为[R13],同时,LDM指令中寄存器和内存地址的位置相对于前面两条指令改变了。

  • LDMFD SP! , {R0, R1, R2}
    实际上可以理解为: LDMFD [SP]!, {R0, R1, R2}意思为:
    把sp指向的3个连续地址段(应该是3*4=12字节(因为为r0,r1,r2都是32位))中的数据拷贝到r0,r1,r2这3个寄存器中去。
STR指令STR指令的格式为:

STR{条件} 源寄存器,<存储器地址>
STR指令用于从源寄存器中将一个32位的字数据传送到存储器中。该指令在程序设计中比较常用,且寻址方式灵活多样,使用方式可参考指令LDR。
指令示例:

  • STR R0,[R1],#8 ;
    将R0中的字数据写入以R1为地址的存储器中,并将新地址R1+8写入R1。
  • STR R0,[R1,#8] ;
    将R0中的字数据写入以R1+8为地址的存储器中。
STRB指令STRB指令的格式为:

STR{条件}B 源寄存器,<存储器地址>
STRB指令用于从源寄存器中将一个8位的字节数据传送到存储器中。该字节数据为源寄存器中的低8位。
指令示例:

  • STRB R0,[R1] ;
    将寄存器R0中的字节数据写入以R1为地址的存储器中。
  • STRB R0,[R1,#8] ;
    将寄存器R0中的字节数据写入以R1+8为地址的存储器中。
STRH指令STRH指令的格式为:

STR{条件}H 源寄存器,<存储器地址>
STRH指令用于从源寄存器中将一个16位的半字数据传送到存储器中。该半字数据为源寄存器中的低16位。
指令示例:

  • STRH R0,[R1] ;
    将寄存器R0中的半字数据写入以R1为地址的存储器中。
  • STRH R0,[R1,#8] ;
    将寄存器R0中的半字数据写入以R1+8为地址的存储器中
STM指令:

S的含义仍然是STORE,与LDM是配对使用的,其指令格式上也相似,即区别于STR,是将堆栈指针写在左边,而把寄存器组写在右边。

  • STMFD SP!, {R0}
    同样的,该指令也可理解为: STMFD [SP]!, {R0}意思是:把R0保存到堆栈(sp指向的地址)中。

- MOV[move]

  • mov R0,R1
    R1的值赋给R0
  • mov R0,#0x100
    R0=0x100

伪指令

  • LDR R0,=0x12345678
    不存在这条指令,
    它会被拆分成几条真正的RAM指令
    R0=0x12345678

sub减法

  • sub R0,R1,#4
    r0=r1-4
  • sub r0,r1,r2
    r0=r1-r2

add加法

  • add,r0,r1,#4
    r0=r1+4

- B:跳转

BL:branch and link

  • bl xxx;
    跳到xxx
    返回地址(下一条指令的地址)保存在LR寄存器中(R14)
    子程序返回调用程序指令 MOV PC,LR

ldm 读内存,写入多个寄存器

  • ldmia sp,(fp,sp,pc)
    [ia:先读后增] – > 后存:(sp,ip,lr,pc) :高编号寄存器存在高地址
    假设 sp=4080
    先读:fp=4080-4083的值=原来保存的fp
    后增:sp‘=sp+4=4084
    先读:sp=4084-4087的值=原来保存的ip寄存器的值
    后增:sp‘=sp+4=4088

    sp=4080,无!,修改后的地址值不存入 sp 中。

其他形式简单的描述指令的行为,意思分别是过后增加(Increment After)、预先增加(Increment Before)过后减少(Decrement After)预先减少(Decrement Before)

stm 把多个寄存器的值写入内存

  • stmdb sp!,(sp,ip,lr,pc)
    !:sp=最终被修改的sp值=4080;
    [ db : 先减后存] – > 后存:(sp,ip,lr,pc) :高编号寄存器存在高地址
内存 内存 内存 内存 地址
PC PC PC PC 4095-4092
lr lr lr lr 4091-4088
ip ip ip ip 4087-4084
fp fp fp fp 4083-4080


假设 :sp=4096
先减:sp’=sp-4=4092
后存:4092-4095 存放PC(r15)的值
先减:sp’=sp-4=4088
后存:4088-4091存放lr(r14)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!