CORTEX-A8裸机系列:第三章 ARM汇编指令集

第三章 ARM汇编指令集

(汇编)指令是CPU机器指令的助记符,经过编译后会得到一串10组成的机器码,可以由CPU读取执行。

(汇编)伪指令本质上不是指令(只是和指令一起写在代码中),他是由编译器环境提供,目的是用来指导编译过程。

1、寻址方式

8种寻址方式

  • 寄存器寻址           mov r1, r2

  • 立即寻址             mov r0, #0xff

  • 寄存器移位寻址       mov r0,r1,lsl #3

  • 寄存器间接寻址       ldr r0,[r2]

  • 基址变址寻址         ldr r1,[r2,#4]

  • 多寄存器寻址         ldmia r1!, {r2-r7,r12}

  • 堆栈寻址             stmfd sp!, {r2-r7,lr}

  • 相对寻址             beq flag

2、指令后缀

统一指令经常附带不同后缀,变成不同的指令

  • B(byte) 功能不变,操作长度变为8位

  • H(half word)功能不变,操作长度变为16位

  • S(signed)功能不变,操作数变成有符号数

  • S(S标志)功能不变,影响CPSR标志位更新

3、CPSR

CPSR是保存系统状态的寄存器。


4、条件执行后缀

ARM指令,支持条件执行,当条件满足条件,指令才会执行,否则该指令,不会被执行。


5、比较指令

比较指令用来比较2个寄存器中数据是否一致,比较指令会影响CPSR的标志位。

Cmp : 两个寄存器数据一样, 标志位Z为1

cmn : 判断两个数是否互补

tst :  测试某些位是否为0,为0,Z为1。Tst r0,#0xf 判断r0的bit0-bit3是否全为0

teq :  两个数异或

6、CPSR访问指令

通过MRS,可以访问CPSR,通过MSR,可以设置CPSR。

7、跳转指令

B   直接跳转

Bl   跳转,保存返回地址

Bx   跳转同时切换ARM/thumb模式。

8、访存指令

单个字/半字/字节访问  ldr,ldrb,ldrh/str,strb,strh

多字批量访问  ldm/stm

swp r1, r2, [r0]  内存和寄存器互换指令  r0的内存地址数据读取到r1中,并把r2的数据写入到r0的内存地址

swp r1, r1, [r0]  实现了r0的内存地址数据和r1寄存器数据互换

9、软中断指令

swi (software interrupt)

软中断指令用来实现操作系统中系统调用

10、多寄存器访问指令

这一类指令,可以从内存同时读取多个数据到寄存器,或者将多个寄存器值写入到内存,当批量读取或写入内存时,使用这一类指令,效率高。

stmia    sp, {r0 – r12}

将r0存入sp指向的内存处(假设为0x30001000);然后地址+4(即指向0x30001004),将r1存入该地址;然后地址再+4(指向0x30001008),将r2存入该地址······直到r12内容放入(0x3000130),指令完成。

一个访存周期同时完成13个寄存器对一段地址空间的写操作。

ldmia    sp, {r0 – r12}

将sp指向的内存处(假设为0x30001000)的数据写入到r0中;然后地址+4(即指向0x30001004),将地址数据写入到r1;然后地址再+4(指向0x30001008),将地址数据写入到r2······直到(0x3000130)地址数据写入到r12中,指令完成。

一个访存周期同时完成13个寄存器对一段地址空间的读操作。

8种后缀

  • ia(increase after)先传输,再地址+4

  • ib(increase before)先地址+4,再传输

  • da(decrease after)先传输,再地址-4

  • db                先地址-4,再传输

  • fd(full decrease)满递减堆栈

  • ed(empty decrease)空递减堆栈

  • fa(·······) 满递增堆栈

  • ea(·······)空递增堆栈

11、^符号作用

在目标寄存器中有pc时,会同时将SPSR写入到CPSR

如指令 ldmfd    sp!, {r0 – r6, pc}^, 当更新PC后,会将SPSR回复到CPSR。

12、GNU伪指令

在写汇编程序的时候,会使用一些伪指令,这些伪指令不是ARM指令,而是编译器提供的指令。

.global  _start                定义全局标号,外部可以使用这个标号

.section  .text                指定当前的段为代码段

.ascii  .byte  .short  .long  .word  .quad  .float  .string          定义数据

.align                               指定地址对齐

.equ                                定义宏,类似于C中宏定义

.balignl  16, 0xdeadbeef

B表示位填充, align 表示要对齐, l表示long,以4字节为单位填充;16表示16字节对齐; 0xdeadbeef是用来填充的原料

如以下:

0x0000_0008:  .balignl  16, 0xdeadbeef

0x0000_000c:   保存0xdeadbeef

0x0000_0010:  下一条数据

如以下:

0x0000_0008:  .balignl  32, 0xdeadbeef

0x0000_000c:   保存0xdeadbeef

0x0000_0010:   保存0xdeadbeef(继续填充,直到32字节)

0x0000_0014:  下一条数据

.arm / .code32    声明以下的代码是ARM指令

.thumb /.code16  声明以下的代码是thumb指令

13、ldr和adr

ldr和adr指令,都可以获取地址值。

ldr   大范围的地址加载指令

adr   小范围的地址加载指令

adrl   中等范围的地址加载指令

adr和ldr

  • adr编译时会被一条sub或add指令替代,而ldr编译时会被一条mov指令替代或者文字池方式处理

  • adr总是以PC为基准来表示地址,因此指令本身和运行地址有关,可以用来检测程序当前的运行地址在哪里

  • ldr加载的地址和链接时给定的地址有关,由链接脚本决定。

因此,adr加载的是相对地址(运行时决定),ldr加载的是绝对地址(链接时决定),因此可以通过adr和ldr加载的地址来判断当前程序是否在链接时指定的地址运行。

此条目发表在CORTEX-A8分类目录,贴了, 标签。将固定链接加入收藏夹。

发表评论

电子邮件地址不会被公开。