arm汇编基础指令及解析附GNU ARM常用伪操作

Arm指令基本格式

<opcode>{<cond>}{s} <rd>,<rn>{,<operand2>}
Opcode :操作码(指令助记符,如mov,ldr)
Cond :可选择的条件码,执行条件,如ne,eq(用于CPSR中值的比较)
S:若有s后缀,则根据计算结果更新cpsr中的条件码/*这个地方需要注意下*/
Rd:目标寄存器
Rn:存放第一个操作数的寄存器
Operand2:第二个操作数

一些其他arm事项:通用寄存器(R0-R15)可分为三类 :
不分组寄存器R0~R7;分组寄存器R8~R14;(SP为R13)程序计数器PC。

在汇编语言中,用分号“;”标识分号后面的语句为注释语句。

arm指令条件码

EQ

Z=1

相等

NE

Z=0

不相等

CS/HS

C=1

无符号数大于或等于

CC/LO

C=0

无符号数小于

MI

N=1

负数

PL

N=0

正数或零

VS

V=1

溢出

VC

V=0

没有溢出

HI

C=1且Z=0

无符号数大于

LS

C=0或Z=1

无符号数小于或等于

GE

N和V相同

有符号数大于或等于

LT

N和V不同

有符号数小于

GT

Z=0且N=V

有符号数大于

LE

Z=1或N!=V

有符号数小于或等于

AL

无条件

无条,跟不写一样

 CPSR寄存器

 

这里用加减法指令引一下cpsr

add r0,r0,#1;表示r0=r0+1
sub r0,r0,#1;表示r0=r0-1

adds表示当有数据超过0xfff(32位),cpsr中的c=1,初始时为0,而subs表示数据变为0时,c=0,初始是1。就比如cmp指令为一减法指令,不相同的两数相减不为0,那没c值就是1,同时cmp会影响z的值,即结果不为0,z=0,c的值变化还有移位操作中,C为移位操作中最后移出位的值
adc r5,r1,r3 ;将进位c也加进来 sbc也是同样道理 
lsrs r0,r0,#1;将r0左移一位,若r0=0x8000,那么c=1,若r0=0x0800,那么c=0
lsls 则表示左移 同时去掉s,lsl和lsr移位就不影响值的改变
add r3,r2,r1,lsl,#2;r3=r2+r1/4(不会保留余数)
N:在结果是有符号的二进制补码情况下,如果结果为负数,则N=1;如果结果为非负数,则N=0。
Z:如果结果为0,则Z=1;如果结果为非零,则Z=0。/*c和z是比较常用的*/
V:对于加减法指令,在操作数和结果是有符号的整数时,如果发生溢出,则V=1;如果无溢出发生,则V=0;对于其他指令,V 通常不发生变化。

msr与mrs可以用来改变cpsr中的值 msr r0 ,cpsr ;r0=cpsr
mrs cpsr,r0;cpsr=r0/*一般修改cpsr是会在cpsr后面加后缀,防止出错,cpsr_f (标志域31-24位),_s状态域23-16,_x扩展域15-8,_c控制域7-0*/

MOV指令

mOV指令的格式为:MOV{条件}{S} 目的寄存器,源操作数
mov r1,r2 ;将寄存器r2的值赋值给r1
mov r1,#0 ;令r1值为0

lar指令与str指令

LDR{条件} 目的寄存器 <存储器地址>/*ldr后面的条件一般接al,即无条件,可以省略*/
str指令格式 STR{条件} 源寄存器,<存储器地址>
前变址: 
ldr r0,[r1,#4] ;[r1+4] →r0,以r4+4为地址,将其对应地址下的数据存入r0
前变址回写:
ldr r0,[r1,#4]! ;r1+4→r1,[r1]→r0
后变址回写:
ldr r0,[r1],#4 ;[r1]→r0,r1+4→r1
ldr r0,=SRC ;取得原数据表的表头,即地址/*比如,r0就是取得1数据的地址
src:
.long 1,2,3,4,5,6
*/
ldr r0,=0x20;此为将0x20的值赋值给r0
str r0,[r1];将r1看成地址,将r0的值存入地址为r1的数据中
!表示自动变址
str与ldr后面+b或h,str表示去字数据,即32位,strh表示半字数据16位,strb表示一字节数据,8位

ldm和stm指令

 LDM{条件}{s}<MODE>基址寄存器{!},{Reglist}
STM{条件}{s}<MODE>基址寄存器{!},{Reglist}
stm与ldm一般用于数据块或多字数据的传送,所以一般配合
ia 操作完后地址递增 ib地址先增后完成操作 da操作完成后地址递减
db 地址先减后完成操作等操作使用
/*多寄存器用{}包含,连续寄存器用-间隔,不连续的寄存器就用,分隔*/
ldmia r0,{r1-r4,r6};r1=[r0].r2=[r0+4],......r6=[r6+16]
ldm以r0为地址,r0地址对应的数据读取存入
stmia r6,{r1-r5};将r1到r5中的数据依次存入r6为起始地址的存储单元
即[r6]=r1,[r6+4]=r2,......,[r6+16]=r5
还可以用于堆栈寻址,采用R13(SP)作为堆栈指针,sp指向栈顶
fd/ed 满递减/空递减    fa/ea 满递增/空递增
stmfd sp!,{r0-r7};将数据从r7开始入栈 ldmfd sp!,{r0-r7};从r7开始弹出堆栈 /*存入时fd起始和db很像,先将sp往下一个地址,然后再将数据存入sp移过的地址中去,取出时fd就和ia很像*/
/*记ldm后面加什么其实很简单,i对应英文 increment 增加 d 对应decrement减少 a表示after在...之后 b对应before在什么之前,然后主语就是地址,ib就是地址增加在前了*/

beq和bne指令

 bne:标志寄存器中Z标志位不等于零时, 跳转到BNE后标签处
beq:标志寄存器中Z标志位等于零时, 跳转到BEQ后标签处  
b是跳转指令 eq和en是arm指令条件码中的
mov r11,#20 /*计数即代表矢量维度*/
    mov r10,#0 /*初始化结果寄存器*/
loop:
    ldr r0,[r8],#4 /*读取矢量1指针*/
    ldr r1,[r9],#4 /*读取矢量2指针*/
    mla r10,r0,r1,r10/*这个是乘法运算指令*/
    subs r11,r11,#1
    bne loop/*其会根据前面r11的值判断,非0就跳转,若是beq就是为0才跳转*/

逻辑运算

add 逻辑与 orr 或 eor 异或 bic清零 格式都一样的
bic r0,r0,#3 ;将r0的第0和1位清零

GNU ARM常用伪操作

 代码行中的注释符号: ‘@’
整行注释符号: ‘#’
(1)符号定义伪操作
.equ symbol,expr  @将symbol定义为expr
.set   @与.equ相同
.global symbol   @将symbol定义为全局标号
.extern symbol   @声明symbol为一个外部变量
(2)数据定义伪操作
.word expr {,expr}  @分配字内存单元并用expr初始化
.byte expr {,expr}   @分配字节内存单元并用expr初始化
.long expr {,expr}   @同.word
.ascii expr{,expr}   @字符串,非零结束符
.string expr {,expr} @字符串,零结束符,同.asciz
.zreo size                    @用0填充size个字节的内存单元
(3)汇编与反汇编控制伪操作
.arm  @定义以下代码用ARM指令集编译,同.code 32
.thumb @定义以下代码用Thumb指令集编译,同.code 16
.end  @汇编结束标志
(3)预定义控制操作
.if          @条件判断语句
.else      @条件判断语句
.endif    @条件判断语句
.macro  @宏定义开始
.endm   @宏定义结束
.exitm   @中途跳转出宏
.include “file_name”  @包含文件标识

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值