汇编入门
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中
参考
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代码
参考
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
通用寄存器
- r0-r3 用作传入函数参数,传出函数返回值。在子程序调用之间,可以将 r0-r3 用于任何用途。被调用函数在返回之前不必恢复 r0-r3。—如果调用函数需要再次使用 r0-r3 的内容,则它必须保留这些内容。
- r4-r11 被用来存放函数的局部变量。如果被调用函数使用了这些寄存器,它在返回之前必须恢复这些寄存器的值。
- r12 是内部调用暂时寄存器 ip。它在过程链接胶合代码(例如,交互操作胶合代码)中用于此角色。在过程调用之间,可以将它用于任何用途。被调用函数在返回之前不必恢复 r12。
- 寄存器 r13 是栈指针 sp。它不能用于任何其它用途。sp 中存放的值在退出被调用函数时必须与进入时的值相同。
- 寄存器 r14 是链接寄存器 lr。如果您保存了返回地址,则可以在调用之间将 r14 用于其它用途,程序返回时要恢复,总是包含着退出时要装载到 pc 中的值。
- 寄存器 r15 是程序计数器 PC。它不能用于任何其它用途,总是包含下一个要被执行的指令的位置。
参考寄存器r0-r15含义