ARM标准汇编:适用于ARM公司的汇编器,适合在windows平台下使用,如ADS中使用
GNU汇编:适用于GUN交叉编译工具链中的汇编器,适合于Linux开发平台
汇编程序框架:
.section .data <初始化的数据> .section .bss <未初始化的数据> .section .text .global _start _start: <汇编代码> |
建立汇编编程环境:汇编文件+链接脚本+Makefile+Ecplise
注意:
mov
MOV 从另一个寄存器、被移位的寄存器、或一个立即值装载一个值到目的寄存器(只能是通用寄存器)。你可以指定相同的寄存器来实现 NOP 指令的效果,你还可以专门移位一个寄存器:
MOV R0, R0 ; R0 = R0... NOP 指令 MOV R0, R0, LSL#3 ; R0 = R0 * 8 |
mvn
在MOV的基础上进行取反之后再装载到目的寄存器
MVN R0, #4 ; R0 = -5 MVN R0, #0 ; R0 = -1 |
sub
SUB 用操作数 one 减去操作数 two,把结果放置到目的寄存器中。操作数 1 是一个寄存器,操作数 2 可以是一个寄存器,被移位的寄存器,或一个立即值:
SUB R0, R1, R2 ; R0 = R1 - R2 SUB R0, R1, #256 ; R0 = R1 - 256 SUB R0, R2, R3,LSL#1 ; R0 = R2 - (R3 << 1) |
add
ADD 将把两个操作数加起来,把结果放置到目的寄存器中。操作数 1 是一个寄存器,操作数 2 可以是一个寄存器,被移位的寄存器,或一个立即值:
ADD R0, R1, R2 ; R0 = R1 + R2 ADD R0, R1, #256 ; R0 = R1 + 256 ADD R0, R2, R3,LSL#1 ; R0 = R2 + (R3 << 1) |
and
AND 将在两个操作数上进行逻辑与,把结果放置到目的寄存器中;对屏蔽你要在上面工作的位很有用。 操作数 1 是一个寄存器,操作数 2 可以是一个寄存器,被移位的寄存器,或一个立即值:
AND R0, R0, #3 ; R0 = 保持 R0 的位0和1,丢弃其余的位。 |
bic
BIC 是在一个字中清除位的一种方法,与 OR 位设置是相反的操作。操作数 2 是一个 32 位位掩码(mask)。如果如果在掩码中设置了某一位,则清除这一位。未设置的掩码位指示此位保持不变。
BIC R0, R0, #%1011 ; 清除 R0 中的位 0、1、和 3。保持其余的不变。 |
以上两条指令可以配合条件来实现条件跳转语句,有以下条件可以使用:
EQ : 等于 如果一次比较之后设置了 Z 标志。 NE : 不等于 如果一次比较之后清除了 Z 标志。 GE : 大于或等于(有符号) 如果一次比较之后... 设置了 N 标志并设置了 V 标志 或者... 清除了 N 标志并清除了 V 标志。 GT : 大于(有符号) 如果一次比较之后... 设置了 N 标志并设置了 V 标志 或者... 清除了 N 标志并清除了 V 标志 并且... 清除了 Z 标志。 LE : 小于或等于(有符号) 如果一次比较之后... 设置了 N 标志并清除了 V 标志 或者... 清除了 N 标志并设置了 V 标志 并且... 设置了 Z 标志。 LT : 小于(有符号) 如果一次比较之后... 设置了 N 标志并清除了 V 标志。 或者... 清除了 N 标志并设置了 V 标志。 |
lsl
Rx, LSL #n or Rx, ASL #n or Rx, LSL Rn or Rx, ASL Rn |
接受 Rx 的内容并按用‘n’或在寄存器 Rn 中指定的数量向高有效位方向移位。最低有效位用零来填充。除了概念上的第 33 位(就是被移出的最小的那位)之外丢弃移出最左端的高位,如果逻辑类指令中 S 位被设置了,则此位将成为从桶式移位器退出时进位标志的值。
考虑下列:
MOV R1, #12 MOV R0, R1, LSL#2 |
在退出时,R0 是 48。 这些指令形成的总和是 R0 = #12, LSL#2 等同于 BASIC 的 R0 = 12 << 2
ror
Rx, ROR #n or Rx, ROR Rn |
循环右移类似于逻辑右移,但是把从右侧移出去的位放置到左侧,如果逻辑类指令中 S 位被设置了,则同时放置到进位标志中,这就是位的‘循环’。一个移位量为 32 的操作将导致输出与输入完全一致,因为所有位都被移位了 32 个位置,又回到了开始时的位置!
msr
复制一个寄存器到 PSR 中
MSR CPSR, R0 ; 复制 R0 到 CPSR 中 MSR SPSR, R0 ; 复制 R0 到 SPSR 中 |
mrs
复制 PSR 到一个寄存器中
MRS R0, CPSR ; 复制 CPSR 到 R0 中 MRS R0, SPSR ; 复制 SPSR 到 R0 中 |
ldr
把数据从内存装载到寄存器
LDR{条件} Rd, <地址> |
str
把数据从寄存器写回内存
STR{条件} Rd, <地址> |
ARM机器码就是指令的二进制代码,通过将elf格式的执行程序进行反汇编后可以查看每条指令的机器码,是一个32位的整数。机器码分为若干个段,每个段可以反映指令本身的一些信息,比如指令的条件类型,操作数类型,操作数的值,是否影响CPSR,寄存器编号等。
伪指令本身并没有所对应的机器码,它只是在编译的时候起作用,或者转化为其他的实际指令来运行。类似于C语言中的预处理指令。
equ:类似于C语言中的宏定义
.equ DA, 0x89 ; DA=0x89 mov r0, #DA ; r0=0x89 |
align:控制对齐
.data hello: .ascii "helloworld" .align 4 bh: .byte 0x1 wd: .word 0xff |
ldr
mov r0, #0x1ff ;出错,对于mov指令,不能使用超过8位的立即数,这根机器码有关 ldr r0, =0x1ff ;正确,对于超过8位的赋值,需要使用ldr伪指令,小于8位也可以使用ldr进行赋值 |
协处理器用于执行特定的任务,比如数学协处理器可以控制数字处理,以减轻处理器的负担。ARM可支持多达16个协处理器,其中CP15是最重要的一个。
协处理器可以用于提供额外的寄存器,用于控制缓存,MMU,保护系统,时钟模式以及其他的CPU选项,比如大小端工作模式。
对CP15的寄存器访问需要通过MCR和MRC来完成。
CP15提供了c0-c15共16组寄存器,在每组下面还有c0-cx若干小组寄存器,每个小组下面还有若干编码的具体寄存器。
MCR:将通用寄存器中的值放到协处理器中
MRC:与MCR相反,将值放回协处理器
You can access CP15 registers with MRC and MCR instructions: MCR{cond} P15,,,,, MRC{cond} P15,,,,, |
示例:
mrc P15, 0, r0, c0, c0, 0 ;将CP15的Main ID寄存器读取到r0中 mcr P15, 0, r0, c1, c0, 0 ;将r0赋值到CP15的Control寄存器 |