ARM常用指令+源码解读

概念阐述:

AREA

段名 属性1,属性2

— CODE 属性:用于定义代码段,默认为READONLY 。

— DATA 属性:用于定义数据段,默认为READWRITE 。

— READONLY 属性:指定本段为只读,代码段默认为READONLY 。

— READWRITE 属性:指定本段为可读可写,数据段的默认属性为READWRITE 。

— ALIGN 属性:使用方式为ALIGN表达式。在默认时,ELF(可执行连接文件)的代码段和数据段是按字对齐的,表达式的取值范围为0~31,相应的对齐方式为2表达式次方。

— COMMON 属性:该属性定义一个通用的段,不包含任何的用户代码和数据。各源文件中同名的COMMON段共享同一段存储单元

ENTRY

ENTRY伪指令用于指定汇编程序的入口点。在一个完整的汇编程序中至少要有一个ENTRY(也可以有多个,当有多个ENTRY时,程序的真正入口点由链接器指定),但在一个源文件里最多只能有一个ENTRY(可以没有)。

IMPORT

标识符表明要调用的函数为本模块外部定义的

EXPORT

标识符表示本模块中定时的符号可以为外部模块使用

EQU

EQU 指令用于将一个数值或寄存器名赋给一个指定的符号名。

用法:①符号名 EQU 表达式

​ ②符号名 EQU 寄存器名

MOV

将源操作数source的值复制到target中去,source值不变

用法:MOV target,source

ADD

将后面的操作数加到前面操作数中

用法:ADD reg/mem reg/mem/imm

SUB

将前面的数减去后面的数,存到前面的寄存器中

用法:SUB reg/mem reg/mem/imm

LDR(指令

与MOV功能类似,相当于立即数没有超过8位执行的MOV指令,使用时没有等号

例1: ldr r0, 0x12345678 // 就是把0x12345678这个地址中的值存放到r0中。而mov不能干这个活,mov只能在寄存器之间移动数据,或者把立即数移动到寄存器中。
例2:ldr r0,r1 //表示把r1寄存器中的值放入r0
例3:ldr r0,[r1] // [r1]表示r1中值对应内存的地址,所以是把r1中的数当作一个地址,把这个地址中的值放入r0

LDR(伪指令

与MOV功能类似,相当于立即数没有超过8位执行的MOV指令,使用时有等号

例1(立即数):LDR r0, =0x12345678 //把0x12345678这个地址写到r0中

例2(标号): LDR r0, =_start //将指定标号的地址赋给r0

DCD

数据定义( Data Definition )伪指令

一般用于为特定的数据分配存储单元,同时可完成已分配存储单元的初始化。

用法:标号 DCD(或 DCDU) 表达式

CMP

(比较)指令执行从目的操作数中减去源操作数的隐含减法操作

用法:CMP destination,source

如果比较的是两个无符号数,则零标志位和进位标志位表示的两个操作数之间的关系如右表所示:

CMP结果 ZF CF
目的操作数 < 源操作数 0 1
目的操作数 > 源操作数 0 0
目的操作数 = 源操作数 1 0

如果比较的是两个有符号数,则符号标志位、零标志位和溢出标志位表示的两个操作数之间的关系如右表所示:

CMP结果 标志位
目的操作数 < 源操作数 SF ≠ OF
目的操作数 > 源操作数 SF=OF
目的操作数 = 源操作数 ZF=1

例1:

MOV ax, 5
CMP ax,10 ; ZF = 0 and CF = 1

例2:

MOV ax,1000
MOV cx,1000
CMP cx, ax ;ZF = 1 and CF = 0

例3:

MOV si,105
CMP si, 0 ; ZF = 0 and CF = 0

B,BL

跳转。BL相当于C中的调用子函数,在跳转的标号最后加上MOV PC,LR 就可以返回BL下一条指令。

BGE

GE是指令条件,意思就是greater or equal,大于或等于,似乎几乎zd可以加到所有指令上。
BGE中的B是回branch,跳转的意思,BGE就是大答于或等于才跳。

BEQ

BEQ(比较相等,EQ为相等) 在BEQ指令前应该有一条比较指令,比如CMP R0,R1 若R0=R1,则执行BEQ指令,否则不执行。

BNE

BNE: 数据跳转指令,标志寄存器中Z标志位不等于零时, 跳转到BNE后标签处。

与b的区别:BNE指令,是个条件跳转,即:是“不相等(或不为0)跳转指令”。如果不为0就跳转到后面指定的地址,继续执行。

B 是最简单的分支。一旦遇到一个 B 指令,ARM 处理器将立即跳转到给定的地址,从那里继续执行。

与BGE的区别:BNE指令会去查看状态寄存器,当Z!=1的时候就跳转到指定位置,BEQ功能与BNE刚好相反,Z==1的时候才跳转到指定位置.

BX

跳转并切换指令集。

bx lr的作用等同于mov pc,lr

可以使用MOV PC, LR或者BX LR来完成子程序返回。另外,也可以在在子程序入口处使用下面的指令将LR保存到栈中

LR

链接寄存器(用来存放子程序的返回地址) LR相当于指针变量,指令在内存中的地址。如果子程序再调用子程序,返前一次调用的子程序的返回地址要存储栈内 。

N 当用两个补码表示的带符号数进行运算时,N=1表示运算的结果为负数;N=0表示运算的结果为正数或零.
Z Z=1表示运算的结果为零,Z=0表示运算的结果非零。
C 可以有4种方法设置C的值:
加法运算(包括CMN):当运算结果产生了进位时(无符号数溢出),C=1,否则C=0。
减法运算(包括CMP):当运算时产生了借位时(无符号数溢出),C=0,否则C=1。
对于包含移位操作的非加/减运算指令,C为移出值的最后一位。
对于其它的非加/减运算指令,C的值通常不会改变。
V 可以有2种方法设置V的值:
对于加减法运算指令,当操作数和运算结果为二进制的补码表示的带符号数时,V=1表示符号位溢出
对于其它的非加/减运算指令,V的值通常不会改变。

DCD

用于分配一片连续的字存储单元并用指定的数据初始化。

明白了一些概念咋们来实战吧~

源码解读:

该程序实现了什么功能呢~?

;routine for find max value in a integer array.
;R1 is the counter of the loop.
;R2 is the pointer of the arraye element. R3 is the value of array element pointed by R2.
;R4 is alway pointing to the max element finded up now,and R5 is the value of the array element pointed by R4.
;在整数数组中查找最大值的例程。
;R1是循环的计数器。
;R2是arraye元素的指针。R3是R2指向的数组元素的值。
;R4总是指向现在找到的max元素,R5是R4指向的数组元素的值。
N EQU 10	;讲N的值定义为10
    AREA findEX01,CODE,READONLY 
    ;这是段名为findEX01(findEX01),可读可写(READONLY)的代码段(CODE)
    ENTRY	;程序开始
    EXPORT findnum	;findnum代码块可以在外部模块使用
findnum		;函数名,该函数用于初始化寄存器R1~R5的值
    MOV R1,#N-1		;将N-1的值存放到寄存器R1中
    LDR R2,=finddata10		;将finddata10的首地址存到R2中
    LDR R3,[R2]		;将R2中的值作为地址,从该地址取出数据存到R3中,finddata10第一个元素的值为0x70,R3将存储0x70
    MOV R4,R2		;将R2的值存放到R4中
    MOV R5,R3		;将R3的值存放到R5中,这两步是为了从首地址开始遍历嘛
findloop02		;函数名,该函数内前半部分用于R2指针遍历数组中的连续单元,中间部分用于比较找出最大值,如果R2指向的值比R5大,将该值的地址存在R4中,该值存在R5中。
    ADD R2,R2,#4	;将R2中的值与4相加存到R2中:储存一个数需要4字节,因此指向下一个数需要偏移4个字节
    LDR R3,[R2]		;将R2的值作为地址,从该地址取出数据存到R3中
    CMP R5,R3		;比较R5和R3的值
    BGE findskip	;当R5>R3时跳到findskip函数,R5<=R3时继续执行
    MOV R4,R2		;将R2的值存到R4中
    MOV R5,R3		;将R3的值存到R5中
findskip		;函数名,用作循环,类似于for(i=9;i>=0;i--)
    SUB R1,R1,#1	;R1自减
    CMP R1,#0		;将R1的值与R0比较
    BNE findloop02	;当R1!=0时,跳转到findloop02函数
    
    BX LR			;等同于 MOV pc,lr, 这里是完成子程序的返回
    
    AREA finddat0,DATA,READWRITE
    ;这是段名为finddat0(finddat0),可读可写(READONLY)的数据段(DATA)
finddata10 DCD 0x70,0x30,0x20,0x80,0x35,0x65,0x55,0x75,0x25,0x60
;分配一段连续的单元地址
	END				;结束模块

所以!它就是开了个数组,找到了数组中的最大元素!写了一晚上,甚至激动QAQ比前一篇文章好一些了,一丢丢基础都没花时间理清关系挺艰辛的qaq碎觉觉了

posted @ 2020-04-08 00:20  碎了的冰  阅读(1747)  评论(5编辑  收藏  举报