卢骏 · 6月29日

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是保存系统状态的寄存器。

1.png

4、条件执行后缀

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

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加载的地址来判断当前程序是否在链接时指定的地址运行。

系列其他篇

原文首发于骏的世界博客
作者:卢骏.
更多Arm技术相关的文章请关注Arm技术博客极术专栏,每日更新。
4 阅读 158
推荐阅读
0 条评论
关注数
6069
内容数
156
Arm相关的技术博客,提供最新Arm技术干货,欢迎关注
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
Arm中国学堂公众号
关注Arm中国学堂
实时获取免费 Arm 教学资源信息
Arm中国招聘公众号
关注Arm中国招聘
实时获取 Arm 中国职位信息