ARM指令与汇编
寻址方式与指令格式
寻址方式
根据指令中地址码字段来寻址操作数地址的方式。
寄存器寻址
操作数的值在寄存器中, 指令中的地址码字段为寄存器编号,指令执行时直接取出寄存器值操作。
MOV R1, R2 ; R2 -> R1 SUB R0, R1, R2 ; R1 - R2 -> R0
立即数寻址
指令中操作码字段后面的地址码部分就是操作数本身, 数据就包含在指令中。取出指令也就取出了可以立即使用的操作数
SUBS R0, R0, #1 ; R0 - 1 -> R0 MOV R0, #0xff00 ; 0xff00 -> R0
寄存器移位寻址
ARM指令集特有的寻址方式, 第2个操作数与第1个操作数结合前先进行移位操作
MOV R0, R2, LSL #3 ; R2的值左移3位,结果放入R0中 ANDS R1, R1, R2, LSL R3 ; R2左移R3位,然后与R1相与,结果存入R1中
可使用的移位操作如下:
*LSL*: 逻辑左移(Logical Shift Left) 低位补0*LSR*: 逻辑右移(Logical Shift Right) 高位补0*ASR*: 算术右移(Arithmetical Shift Right) 移位过程中保持符号位不变,即如果源操作数为正数,则高位补0, 如果源操作数为负数,则高位补1*ROR*: 循环右移(Rotate Right) 字的低端移出的位填入高端空出的位。*RRX*: 带扩展的循环右移(Rotate Right eXtended by 1 place) 操作数右移移位,高端空出的位用原C标志填充。
寄存器间接寻址
指令中地址码给出的是寄存器编号,操作数保存在寄存器指定地址的存储单元中,即寄存器存放的是操作数的地址
LDR R1, [R2] ; R2中为操作数的地址,取出地址中的数据保存在R1中
基址寻址
将寄存器中的内容与给定的偏移量相加,得到操作数的有效地址。 基址寻址用于访问基址附近的存储单元,一般用于查表,数组操作…
LDR R2, [R3, #0x0f] ; 将R3中的数值作为基址加上0xf作为操作数的地址,取出地址的数据保存在R2中。 STR R1, [R0, #-2] ; 将R0中的数值作为基址减2作为操作数的地址,把R1中的内容保存在此地址中。
多寄存器寻址
一次可以传送多个寄存器的值,允许一条指令传送16个寄存器的任何子集
LDMIA R1!, {R2-R7, R12} ; R1指向地址中的数据读出到R2到R7和R12中, R1自动加1 STMIA R0!, {R3-R6, R10} ; 将R3-R6和R10中的数据保存在R0指定的地址中,R0自动加1
寄存器子集的顺序由小到大排列,连续的寄存器可用“-“连接,否则用”,”分开书写
I: 地址增加D: 地址减小A: 数据读取后,地址加减B: 数据读取前, 地址加减
堆栈寻址
堆栈是按特定顺序进行存取的存储区,操作顺序为“先进后出” 或 “后进先出” 堆栈寻址使用一个专门的寄存器(堆栈指针sp)指向一块存储区域,指针指向的存储单元就是堆栈的栈顶。
生长方向 递增堆栈: 向高地址方向生长 Ascend 递减堆栈: 向低地址方向生长 Descend
根据堆栈指针指向的位置又可以分为满堆栈和空堆栈 满堆栈: 堆栈指针指向最后压入堆栈的有效数据项 Full 空堆栈: 堆栈指针指向下一个要压入的空位置 Empty
根据生长方向和堆栈指针位置可以组合出来4种类型的堆栈
满递增: 堆栈通过增大存储器的地址向上增长,堆栈指针指向含有有效数据项的最高地址。指令如 LDMFA STMFA等 空递增: 堆栈通过增大存储器的地址向上增长,堆栈指针指向堆栈上的第一个空位置。指令如 LDMEA STMEA等 满递减: 堆栈通过减小存储器的地址向下增长,堆栈指针指向含有有效数据项的最低地址。指令如 LDMFD STMFD等 空递减: 堆栈通过减小存储器的地址向下增长,堆栈指针指向堆栈的下一个空地址。指令如 LDMED STMED等
举例:
STMFD SP!, {R1-R7, LR} ; 将R1-R7, LR入栈, 满递减堆栈 LDMFD SP!, {R1-R7, LR} ; 数据出栈,存放如R1-R7, LR , 满递减堆栈
相对寻址
相对寻址是基址寻址的一种变通,由PC提供基址,指令总的地址码字段作为偏移量,两者相加后得到的值为操作数的有效地址。
例:
BL ROUTE1 ; 跳转到ROUTE1子程序 BEQ LOOP ; 条件跳转到LOOP标号
Processor Modes and CPSR
工作模式
User User mode, 程序通常运行在这种模式下FIQ (entered when a high priority (fast) interrupt raised)IRQ (entered when a low priority (normal) interrupt raised)Supervisor (entered on reset and when a Software Interrupt instruction is executed)Abort (used to handle memory access violations)Undef (used to handle undefined instructions)System (特权工作模式,和User Mode使用同一套寄存器)
寄存器组织
![ARM Register Organisation][ARM Register]
ARM总共有37个寄存器,每个寄存器都是32bit
1个用于PC(程序计数器) 1个用于当前的程序状态寄存器CPSR 5个用于保存程序状态寄存器SPSR 30个通用寄存器
这些寄存器根据工作模式分为7组
R13 用于堆栈指针SP R14 用于连接寄存器LR R15 用于程序计数器
程序状态字寄存器
![ARM CPSR Register][ARM CPSR]
条件码标志 copies of the ALU status flags
N = Negative result from ALU flagZ = Zero result from ALU flagC = ALU operation Carried out (进位)V = ALU operation oVerflowed (溢出)
Interrupt Disable bits Bit[7:6]
I = 1, disable the IRQF = 1, disable the FIQ
ARM/Thumb Mode Bit[5]
T = 0, ARM stateT = 1, Thumb state
Working mode Bit[4:0]
程序计数器PC(R15)
当处理器在ARM模式下执行时: 所有指令长度为32bit 所有指令必须以字对齐,所以PC指针的bit[1:0]应该等于0
当跳转指令执行时,R14用于保存根据PC计算得到的返回地址
异常处理
异常向量表
![ARM exception vector table][ARM Exception Vector Table]
异常处理流程 异常产生时:
. 拷贝CPSR to SPSR_<mode> . 设置相应的CPSR状态位 . 将返回地址存储在LR_<Mode> . 将PC设置为对应的向量地址
从异常返回:
. 将SPSR_<mode>恢复到CPSR . 将LR_<mode>恢复到PC
ARM指令格式
基本格式
<opcode> {<cond>} {S} <Rd>,<Rn> {,<operand2>} <>内的项是必须的, {}内的项是可选的
opcode 指令助记符, 如 LDR, STR等cond 执行条件,如EQ,NE等,如果没有指定cond,则默认为AL(无条件执行)S 是否影响CPSR的条件码标志Rd 目的寄存器Rn 第一个操作数的寄存器operand2 第二个操作数
第二操作数operand2
`立即数#immed_8r`
立即数,该常数必须对应8位位图,即该常数由一个8位的常数循环移位偶数位得到
合法常量:
0x3FC, 0, 0xF0000000, 200,
非法常量:
0x1FE, 511, 0xFFFF, 0x1010, 0xF0000010
例: MOV R1, #1
寄存器方式 Rm
操作数为寄存器的值 例如:
SUB R1, R1, R2 ; R1 - R2 → R1 MOV PC, R1 ; PC = R1
寄存器移位方式 Rm, shift
将寄存器移位后的结果作为操作数,但寄存器Rm的值保持不变
ADD R1, R1, LSL #3 ; R1 = R1 * 9 SUB R1, R1, R2, LSR #2 ; R1 = R1 - R2 / 4
条件码 cond
![ARM condition code][ARM Condition Code]
对于thum指令集,只有B指令具有条件执行能力
哈弗结构与冯.诺依曼结构
the Harvard architectrue
哈弗结构是一种将指令和数据分开存储的计算机结构。Harvard architecture这一术语来源于Harvard Mark I型继电器式计算机。 Hardvard Mark I是IBM的自动顺序控制计算机ASCC(Automatic Sequence Controlled Calculator), 被哈佛大学的研究人员称为Mark I(马克一号) Mark I 将指令存储在纸带上,数据存储在机电计数器上,处理器首先到指令存储器中读取指令内容,解码后得到数据地址,再到相应的数据存储器中读取数据。 程序指令和数据分开存储。数据和指令的存取可以分开进行,可以是指令和数据的有不同的宽度。
使用哈佛结构的处理器和微控制器有很多,例如Atmel的AVR系列,ARM公司的ARM9, ARM10, ARM11… …
![the Hardvard architecture, from wikipedia][Harvard Architecture]
the von Neumann architecture
![the von Neumann architectrue, from wikipedia][Von Neumann Architecture]
冯诺依曼体系结构描述了一种电子数字计算机,由以下几部分组成: 1. Processing unit: ALU(arithmetic logic unit, processor registers) 2. Control unit: instruction register and Program Counter 3. a memory to store both data and instructions 4. input and output machanisms
典型情况下完成一个指令需要3个步骤: 取指,译码,执行。 由于取指令和存取数据都需要从同一个存储空间存取,并使用同一总线传输。他们不能重叠执行,只能顺序执行。