汇编入门(持续更新)

汇编入门

ARM汇编与ARM GNU汇编 区别
汇编风格有多种,linux下的gcc是at&t的汇编,此外还有intel和ARM的汇编
开始在Linux下使用汇编语言
不同风格注释方式都不一样
GNU ARM 汇编

汇编(ARM)

LDR

LDR{条件} 目的寄存器 <存储器地址>

LDR指令用于从存储器中将一个32位的字数据传送到目的寄存器中。该指令通常用于从存储器中读取32位的字数据到通用寄存器,然后对数据进行处理。当程序计数器PC作为目的寄存器时,指令从存储器中读取的字数据被当作目的地址,从而可以实现程序流程的跳转。LDR可以访问内存,这是mov做不到的。

LDR R0,[R1];存储器地址为R1的字数据读入寄存器R0

STRB

STRB{条件} 源寄存器,<存储器地址>

STRB指令用于从源寄存器中将一个8位的字节数据传送到存储器中。该字节数据为源寄存器中的低8位。

STRB R0,[R1]将寄存器R0中的字节数据写入以R1为地址的存储器中。

MOV 目的寄存器 <储存器地址/立即数>

MOV 指令用于将一个内存操作数的值“复制”到另一个内存操作数,MOV指令只能用于寄存器间、寄存器立即数间的数据传输

MOV    R0, #0   ;将0(立即数)存入R0

和LDR的区别

LDR可以在内存间操作,MOV只能在寄存器和立即数之间操作,另外MOV限制了立即数大小为8位参考

STR

STR{条件} 源寄存器,<存储器地址>

STR指令用于从源寄存器中将一个32位的字数据传送到存储器中

STR     R1,[R0]     ;将R1中的内容传输到R0中的数所指定的地址的内存中去

功能和LDR正好相反参考

等号=

伪指令,方便阅读源码

创建变量
count=100       ;便于阅读
表明值
ldr r0, =0x12345678          ;   把0x12345678送到r0
ldr r0, 0x12345678            ;  把地址为0x12345678里的数据送到r0

井号#

表明立即数

mov r1 #100           ;  不加#号可能会报错

分号;

用于注释,相当于c里面的//,如果是AT&T版本的汇编,则注释一行使用’#’

MSR和MRS(只能通过这两个指令读写状态寄存器的数据)

MRS

状态寄存器到通用寄存器的传送指令

MRS    R1,CPSR    ;将CPSR状态寄存器读取,保存到R1中
MRS    R2,SPSR    ;将SPSR状态寄存器读取,保存到R2中

MSR

通用寄存器到状态寄存器的传送指令

MSR     PSP, R0     ;将R0寄存器的内容写入psp中

参考

ARM汇编:MRS和MSR指令

BX LR

当通过BL或BLX指令调用子程序时,硬件自动将子程序返回地址保存在R14寄存器中。在子程序返回时,把LR的值复制到程序计数器PC即可实现子程序返回。
相当于返回return;即返回调用当前函数的代码

end

汇编代码运行结尾,如果没有返回,又没有end或者其他能够结束汇编代码的代码,那么汇编代码将会运行到最后

方括号[]

用于表示地址实体,相当于c语言的*

LDR     R0, =OSTCBCurPtr                                    ; 获取OSTCBCurPtr的地址到R0,相当于R0=&OSTCBCurPtr;
LDR     R1, =OSTCBHighRdyPtr                                ; 获取OSTCBHighRdyPtr的地址到R1
LDR     R2, [R1]                                            ; 将R1地址所表式的内容存入R2寄存器,相当于R2=*R1;
STR     R2, [R0]                                            ; 将R2寄存器的值传入R0寄存器所指向地址的内容实体,相当于*R0=R2;

CBZ

比较,为零则跳转;比较,为非零则跳转
CBZ Rn, label
将Rn和0比较,为0则跳转lable

MRS     R0, PSP  
CBZ     R0, PendSVHandler_nosave                     ; 判断psp是不是0,零则跳转后面的代码

还有一个CBNZ,对比非零,使用方法类似

PUSH

将寄存器的内容压入一个完整的降序堆栈。
PUSH{cond} reglist
cond:可选条件代码
reglist:是一个非空的寄存器列表,用大括号括起来。它可以包含寄存器范围。必须用逗号分隔包含多个寄存器或寄存器范围

PUSH    {R14}           ;将R14入栈
PUSH    {R14,R5}        ;将R14、R5入栈(压入当前sp指向的堆栈)

BLX

BLX 指令从ARM 指令集跳转到指令中所指定的目标地址,并将处理器的工作状态由ARM 状态切换到Thumb 状态,该指令同时将PC 的当前内容保存到寄存器R14 中。
BLX 目标地址

LDR     R0, =OSTaskSwHook                                   ; OSTaskSwHook();将OSTaskSwHook函数地址保存到R0
BLX     R0                                                  ; 相当于跳转到OSTaskSwHook运行C代码

参考

汇编跳转指令B、BL、BX、BLX 和 BXJ的区别

LDM

批量出栈操作
LDM R0, {R4-R11} ;将R0表示的地址开始,把数据会写到寄存器R4-R11

SUBS

SUBS 指令是ARM 指令集中的减法指令,与SUB 指令类似,需要注意的是,在SUBS 指令中,如果发生了借位操作,CPSR 寄存器中的 C 标志位设置为 0;如果没有发生借位操作,CPSR 寄存器中的 C 标志位设置成 1 。这与 ADDS 指令中的进位指令正好相反。这主要是为了适应 SBC 等指令的操作需要。

SUBS {} , , <shifter_operand>
指令执行的条件码。当忽略时为无条件执行。
目标寄存器
第一个操作数所在的寄存器
<shifter_operand> 第二个操作数

SUBS    R0, R0, #0x20           ;R0=R0-0x20

STM

将寄存器的值存到地址上

STM{cond} mode Rn{!}, reglist{^}
Rn:基址寄存器,装有传送数据的起始地址,Rn不允许为R15;
!:表示最后的地址写回到Rn中;
reglist:可包含多于一个寄存器范围,用“,”隔开,如{R1,R2,R6-R9},寄存器由小到大顺序排列;
^:不允许在用户模式和系统模式下运行

STM     R0, {R4-R11}         ;将R4-R11寄存器的值从R0的位置开始写入(由低到高地址)

参考

ARM的六大类指令集—LDR、LDRB、LDRH、LDM、STR、STRB、STRH、STM
ARM LDR与MOV的区别
ARM指令官方

寄存器

状态、通用寄存器

状态寄存器

CPSR

SPSR

通用寄存器

  1. r0-r3 用作传入函数参数,传出函数返回值。在子程序调用之间,可以将 r0-r3 用于任何用途。被调用函数在返回之前不必恢复 r0-r3。—如果调用函数需要再次使用 r0-r3 的内容,则它必须保留这些内容。
  2. r4-r11 被用来存放函数的局部变量。如果被调用函数使用了这些寄存器,它在返回之前必须恢复这些寄存器的值。
  3. r12 是内部调用暂时寄存器 ip。它在过程链接胶合代码(例如,交互操作胶合代码)中用于此角色。在过程调用之间,可以将它用于任何用途。被调用函数在返回之前不必恢复 r12。
  4. 寄存器 r13 是栈指针 sp。它不能用于任何其它用途。sp 中存放的值在退出被调用函数时必须与进入时的值相同。
  5. 寄存器 r14 是链接寄存器 lr。如果您保存了返回地址,则可以在调用之间将 r14 用于其它用途,程序返回时要恢复,总是包含着退出时要装载到 pc 中的值。
  6. 寄存器 r15 是程序计数器 PC。它不能用于任何其它用途,总是包含下一个要被执行的指令的位置。
    参考寄存器r0-r15含义
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值