ARM汇编编程基础之三 —— 基本寻址方式与基本指令

 原文作者地址:http://user.qzone.qq.com/308337370/                                        原作者的大作,小弟钦慕而转  

要想进行ARM的汇编编程,首当其冲要知道最基本、最常用的指令,而要了解指令则必须要了解寻址方式。所以本文将聚焦在——基本寻址方式和基本指令。­

    首先,来看一看我们已经见过的2条指令:MOV pc, lr; BL addsub­

    最简单的汇编指令格式是操作码(例如:MOV、BL)和操作数(例如:pc, lr, addsub)。操作码易于理解,例如MOV表示将某个值从一处传送到另一处,BL表示跳转到某处;而操作数则表示一处和另一处到底是哪里(是在寄存器中还是内存中),要跳转的位置在哪里(或者是绝对地址或者是相对地址)。­

    操作数部分要解决的问题是:到哪里去获得操作数?因此就有了寻址方式的分类。基本上来讲,ARM共有8种寻址方式,本文我们了解其中最基本的3种寻址方式:寄存器寻址、立即数寻址、寄存器间接寻址。­

    1、寄存器寻址­

    MOV pc, lr 表示操作数来源于寄存器(pc和lr)。这种寻址方式,在指令的32位机器码中的地址码部分,存放的是寄存器(pc和lr)的编号,故称之为寄存器寻址。­

    2、立即数寻址­

    MOV pc, #64 表示将常数64放入寄存器pc,其中常数64被称为立即数。立即数寻址指令中的地址码部分就是操作数本身,也就是说,数据就包含在指令当中,取出指令也就取出了可以立即使用的操作数(故称为立即数)。­

    这里,可能大家会看出一个问题:由于立即数是位于32位机器码中的,而32位机器码中除了操作数外还有操作码,这就意味着不可能用全部32bit来表示立即数。事实上,ARM机器指令中,仅用了最低的12bit来表示立即数。那么我们自然推论立即数的范围是-2048——2047,这意味着MOV pc, #8192这样的指令是非法的。但事实情况并非如此,MOV pc,#8192是合法且能正常运行的。真实情况是,ARM机器指令可以表示的立即数范围是-2^31--2^31-1,只不过它只能表示这其中的2^12个数而已。ARM是这样用12bit来表示1个立即数的:将12bit划分为2部分——高4位和低8位,将低8位补0扩展为32位,然后循环右移X位(X = 高4位表示的无符号整数*2),例如:如果32位机器码中低12bit为0x512,则其表示的立即数为0x04800000­

图片­

    这里,请大家不妨现在先思考2个问题,我们将在后续文章中予以解答:­

    1)、为什么ARM要这样设计,而不是按照我们最常见的想法(即:12bit就表示-2^11 -- 2^11-1中的数)­

    2)、如果我们需要mov r0, #10000这样的指令,应该怎么办?(常数10000不能按照如上的方法进行表示)­

    3、寄存器间接寻址­

    寄存器间接寻址指令中的地址码给出的是一个通用寄存器的编号,所需的操作数保存在寄存器指定地址的存储单元中,即寄存器为操作数的地址指针。例如:  LDR R0, [R2]表示将R2的值作为内存地址,到该内存处取出存放的数,放到寄存器R0中

   图片图片  

             执行LDR R0, [R2]前的情况              执行LDR R0, [R2]后的情况  ­

­

    了解了基本的寻址方式后,我们现在来看一看最常用的汇编指令­

    1、单寄存器加载指令。主要有­

    加载字指令:LDR r0, [r1],将内存中的一个字(4个字节)加载到寄存器r0中

    加载字节指令:LDRB r0, [r1],将内存中的一个字节加载到寄存器r0中­

    有符号数加载字节指令:LDRSB r0, [r1],这条指令与上一条指令的不同之处在于,由于加载的是一个字节,而不是一个字,所以需要确定寄存器r0的高24bit是什么。对于上一条指令,r0的高24bit补0,而本条指令,r0的高24bit补符号位,也就是补r0的bit7­

    2、单寄存器存储指令。主要有­

    存储字指令:STR r0, [r1],将r0中的值存储到内存的4个字节中­

    存储字节指令:STRB r0, [r1],将r0的低8bit存储到内存的1个字节中­

    3、分支指令,共3条:B、BL、BX  B label :跳转到标号label处,也就是说在该条b指令执行后,下一条执行的指令是标号label处的指令。  BL label :与B指令的功能相同,也实现跳转,不同之处在于,bl在跳转的同时还要将返回地址(bl指令的下一条指令的地址)保存到lr中  BX r0 :将r0的值作为地址,跳转到该地址处,并根据r0的值决定是否在ARM和thumb态之间进行切换。(关于BX指令,以及ARM态和thumb态的切换,详见“ARM程序与thumb程序的切换”一文)  特别说明:  B和BL指令,其跳转范围限制在当前指令的±32M字节地址内(ARM指令为字对齐,最低2位地址固定为0)。这是为什么呢?详见“杂项解释”一文。  4、数据处理指令  MOV r0, r1:将r1的值赋给r0  ADD(SUB) r0, r1, r2:将r1的值加上(减去)r2的值,结果存放到r0中  AND(ORR, EOR) r0, r1, r2:将r1的值与(或、异或)r2的值,结果存放到r0中  CMP r1, r2:比较r1与r2值的大小  ­

­

    特别需要说明的问题:­

    指令CMP r1,r2,其作用细节是:执行r1-r2的操作,如果结果为负数,则置位CPSR的N位,清零Z位;结果为0,则清零CPSR的N位,置位Z位;结果为正,则清零CPSR的N位,清零Z位。但r1-r2的结果并不保存。CMP指令通常用于分支跳转。例如,如下的C程序­

int i,j;­

if (i == j) {­

i++;­

} else {­

j++;­

    如果使用汇编语句改写的话,就应该写为:­

  使用ldr指令将变量i的值放入r0­

  使用ldr指令将变量j的值放入r1­

  cmp r0, r1­

  addeq r0, r0, #1­

  使用streq指令将r0的值放入变量i中­

  beq label­

  add r1, r1, #1­

  使用str指令将r1的值放入变量j中­

label 其它代码­

……­

    其中addeq, streq, beq这几条指令,是add, str, b指令的条件执行版本。讲到这里就不得不讲解一下什么是条件执行了。ARM指令集的所有指令均支持条件执行,条件执行指的是,指令可以根据执行时的情况(CPSR的条件代码标志位)决定自身是否被执行。eq表示如果CPSR的Z位为1(对于本程序,实际上就是r0的值与r1的值相等,因为cmp会根据r0与r1的值设置Z位)的情况下,该指令要执行,否则不执行。­

    其它条件助记符如下:

条件助记符

标志

含义

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

任何

无条件执行 (指令默认条件)

NV

任何

从不执行(不要使用)

­  

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值