ARM汇编指令

接下来的几节我们从实用角度出发,学习ARM常用的一些汇编指令,如存储器访问指令,数据传送指令,算数逻辑运算指令,跳转指令等。一个完整的ARM指令通常由操作码,和操作数完成,指令的编码格式如下。

    opcode cond s Rd Rn, operand2

 这是一个完整的ARM指令需要遵循的格式规则,指令格式的具体说明如下。

使用<>标起来时必选项,使用{}标起来的是可选项。

opcode 是二进制机器指令的操作码助记符,如MOV, ADD这些汇编指令都是操作码的指令助记符。

cond 执行条件,ARM为了减少分支跳转指令个数,允许类似BEQ,BNE等形式的组合指令。

S 是否影响CPSR寄存器中的标志位,比如SUBS指令会影响CPSR寄存器中的N,C, V标志,而SUB指令不会。

Rd 目标寄存器

Rn 第一个操作数的寄存器。

operand2 第二个可选操作数,灵活使用第二个操作数可以提高代码效率。

 在熟悉了ARM指令的基本格式后,开始学一些常用的ARM汇编指令。

3.2.1 存储访问指令

ARM指令集数语 RISC指令集,RISC处理器采用典型的加载/存储体系结构,CPU无法对内存里面的数据直接操作,只能通过Load/Store指令来实现,当我们需要对内存中的数据进行操作时,要首先将这个数据从内存加载到寄存器,然后在寄存器中对数据进行处理,然后将结果重新存储到内存重,ARM处理器属于冯,诺依曼结构,程序和数据存储在同以存储器,内存空间和IO空间统一编写地址,ARM处理器对程序指令,数据,IO空间中外设寄存器的访问都要通过load/store指令来完成,ARM处理器中经常使用的Load/Store指令的使用方法如下。

LDR R1,[R0] 将R0 中的值作为地址,将该地址上的数据保存到R1

STR R1,[R0] 将R0中的值作为地址,将R1中的存储到这个内存地址。

Loat/Strb 每次读写一个字节,LDR/STR默认都读写4个字节。

LDM/STM 批量加载/存储指令,在一组寄存器和一片内存之间传输数据。

SWP R1,R1,[R0] 将R1与R0中地址指向的内存单元的数据进行交换,

SWP R1,R2,[R0] 将R0 存储到R1 ,将R2写入R0这个内存存储单元。

    在ARM存储访问指令中,我们经常使用的是LDR/STR,LDM/STM这两对指令,LDR/STR指令是ARM汇编程序中使用频率最高的一对指令,每一组寄存器到一片连续的内存,通过和堆栈格式符组合使用,LDM/STM指令还可以用来模拟堆栈操作,LDM/STM指令常和表3-2 的堆栈格式组合使用。

     表 3-2 不同类型的堆栈

 堆栈格式    说明   备注

FA

FD

EA

ED

    如图3-3所示,在一个堆栈内存结构中,如果堆栈指针SP总是指向栈顶元素,那么这个栈就是满栈;如果堆栈指针SP指向的是栈顶元素的下一个空闲的存储单元,那么这个栈就是空栈。

SP 满栈

1

2

3

SP 空栈

1

2

3

SP增长方向

 每入栈一个元素,栈指针SP都会往栈增长的方向移动一个存储单元。如果栈指针SP从高地址往低地址移动,那么这个栈就是递减栈;如果栈指针SP从低地址往高地址移动。那么这个栈就是递减栈。ARM处理器使用的一般都是满递减堆栈,在将一组寄存器入栈,或者从栈中弹出一组寄存器时,我们可以使用下面的指令。

LDMFD SP!,{R0-R2,R14} 将内存栈中数据以此弹出到R14,R2,R1,R0

STMFD,SP!, {R0-R2,R14} 

   这里需要注意一个细节是,在入栈和出栈过程中需要留意栈中各个元素的入栈出栈顺序,栈的特点是先入后出,栈元素在入栈操作时候,STMFD会根据大括号{}中寄存器列表中各个寄存器的顺序,从左往右依次压入堆栈。在上面的例子中,R0会先入栈,接着R1,R2入栈,最后R14入栈,入栈操作完成后,栈指针SP在内存中的位置如图3-4左侧所示,栈元素在出栈操作时,顺序刚好相反,栈中元素先弹出到R14寄存器中,接着是R2,R1,R0将栈中的元素依次弹出到R14,R2寄存器后,堆栈指针在内存中的位置如图3-4右侧所示。

SP

R0

R1

R2

R14

SP

R0

R1

地址-->SP增长方向 -->低地址

 除此之外,ARM还专门提供了PUSH和POP指令来执行栈元素的入栈和出栈操作,PUSH和POP指令的使用方法如下。

PUSH {R0-R2,R14}

POP {R0-R2,R14}

你可能感兴趣的:(arm开发,汇编)