ARM汇编笔记之一
ARM的体系架构
哈佛架构
寄存器
指令集
ARM指令是32位指令,即每个指令都是固定长度32位。一般ARM指令的主体采用三个字母的缩写,例如MOV。在此基础上会增加条件判断等一些额外的信息,生成最终指令,例如MOVNE。
分类
- 数据操作类: 最主要的一类指令,完成大部分功能,例如ADD、CMP
- 加载保存类: 用于加载或者保存一个寄存器的指令,例如LDR、STR
- 分支类: 通过修改PC寄存器控制程序执行的指令
- SWI类: 软中断,可以用于调用预定义的方法
- 浮点运算类: 通过协处理器执行浮点运算的指令
指令结构
下面举例说明各类指令的结构:
数据操作类指令:
ADD{cond}{S} <dest> <lhs> <rhs>{,shift}
其中:{cond}表示条件,可用的条件标识见下面说明。如果没有指定,就默认是总是执行该指令。
{S}表示是否设置标志位,如果有S,表示会根据指令执行结果设置标志位。
<dest>是保存结果的目标寄存器
<lhs>是左操作数,必须是寄存器
<rhs>是右操作数,可以是寄存器或者立即数。
{,shift}是对右操作数的移位指令。
{cond}可选的条件主要有
AL(always),NV(never),
EQ(equal,标志位Z设置时为真),NE(not equal,标志位Z清除时为真),VS(overflow set,标志位V设置时是真),VC(overflow clear,标志位V清除时是真),MI(minus,标志位N设置时是真),PL(plus,标志位N清除时为真),CS(carry set,标志位C设置时为真),CC(carry clear,标志位C清除时是真)
HI(higher,上条CMP或SUB指令的左操作数大于右操作数时为真,无符号),LS(lower or same,与HI相反)
GE(greater or equal),LT(less than),GT(greater than),LE(less or equal):这四个条件与HI/LS类似,只是把操作数作为有符号数来处理。
标志位有N(negative)、Z(zero)、V(overflow)、C(carry)。当设置S时,逻辑指令会根据结果修改N、Z,根据右操作数的移位修改C;而算术指令会根据结果修改N、Z、V、C。
逻辑指令的修改逻辑如下:
- 如果运算结果是负数(bit31=1),N置位,否则清除
- 如果运算结果是0,Z置位,否则清除
- 如果<rhs>设置了移位,则C由移位结果设置,否则不修改
- V不修改
算术指令的修改逻辑如下:
- 如果运算结果是负数(bit31=1),N置位,否则清除
- 如果运算结果是0,Z置位,否则清除
- 如果运算结果产生进位,则设置C,否则清除
- 如果运算结果产生溢出,则设置V,否则清除
如果右操作数是立即数,数值范围是有限制的。数据操作类指令是有12位空闲的,理论上可以存储[0,4095]或者[-2048,2047],但是考虑到R15寄存器的26..31位是存储了标志位的,ARM对立即数的存储做了限制,分为两段,高4位是位置信息(实际是值部分的循环右移位数),剩余8位是值,因此立即数的范围是[0,255]。
右操作数在传输给ALU进行计算之前还可以进行一些处理,主要是移位(包括逻辑移位和算数移位)和旋转(rotate)。
加载保存类指令结构:
STR{cond} <src>, [base{,<offset>}]
其中:
src是寄存器,保存着要存储的值
base是寄存器,保存目标位置的基地址
offset是可选的地址偏移量,可以是立即数或者寄存器。如果是寄存器,与数值操作指令的右操作数一样,可以先执行移位。
如果目标地址后面增加!,那么存储完数据后会更新base,指向下一个存储位置,相当于立即执行ADD base,base,offset。
STR指令默认是操作一个word,如果想操作一个字节,需要使用STRB指令。
STR指令还有一个post-indexing模式,STR{cond} <src>,[<base>],<offset>,即先存储再更新base。