Arm笔记

参考文件

arm指令手册1 arm指令手册2 arm指令手册3

  • 流水线
  • DSP
  • Jazelle
  • ThumbEE
  • Thumb-2
  • TrustZone
  • VFP
  • NEON
  • LAPE
  • big.LITTLE
文件名详解
addr2line把程序地址转化为文件名和行号
ar建立、修改和提取归档文件
as汇编编译器
ld链接器
nm列出文件的符号
objcopy文件个数格式转换
objdump反汇编
ranlib产生索引,并且保存进入文件中
readelf显示elf文件信息
size列出文件大小
string打印文件可打印字符串
strip丢弃文件符号

交叉工具链测试

shell

arm-none-eabi-addr2line      arm-none-eabi-gdb
arm-none-eabi-ar             arm-none-eabi-gdb-add-index
arm-none-eabi-as             arm-none-eabi-gfortran
arm-none-eabi-c++            arm-none-eabi-gprof
arm-none-eabi-c++filt        arm-none-eabi-ld
arm-none-eabi-cpp            arm-none-eabi-ld.bfd
arm-none-eabi-dwp            arm-none-eabi-ld.gold
arm-none-eabi-elfedit        arm-none-eabi-lto-dump
arm-none-eabi-g++            arm-none-eabi-nm
arm-none-eabi-gcc            arm-none-eabi-objcopy
arm-none-eabi-gcc-10.2.1     arm-none-eabi-objdump
arm-none-eabi-gcc-ar         arm-none-eabi-ranlib
arm-none-eabi-gcc-nm         arm-none-eabi-readelf
arm-none-eabi-gcc-ranlib     arm-none-eabi-size
arm-none-eabi-gcov           arm-none-eabi-strings
arm-none-eabi-gcov-dump      arm-none-eabi-strip
arm-none-eabi-gcov-tool
模式编码功能安全优先级
User (USR)10000大多数运行的非特权模式BothPL0
FIQ10001FIQ中断BothPL1
IRQ10010IRQ中断BothPL1
Supervisor (SVC)10011设备重启或者SVC指令BothPL1
Monitor (MON)10110安全扩展实现onlyPL1
Abort (ABT)10111内存权限异常BothPL1
Hyp (HYP)11010虚拟化扩展实现.Non-securePL2
Undef (UND)11011未定义指令调用BothPL1
System (SYS)11111特权模式,与用户模式共享寄存器BothPL1

不同的处理器模式上寄存器共享的情况

ARM处理器

指令条件码由CPSR/SPSR同时确定

image-20221007201037402

  • 立即数寻址
  • 寄存器寻址
  • 寄存器间接寻址
  • 寄存器偏移寻址
  • 寄存器基址变址寻址
  • 批量寄存器寻址
  • 相对寻址
  • 堆栈寻址
  • 块拷贝寻址

立即数为操作数,其中立即数前面加上#

asm

    ;; 立即数寻址
	mov r0, #0	; r0 = 0
	mov r1, #64	; r1 = 64

寄存器寻址就是直接将寄存器中的数值作为操作数

指令作用
LSLLogical Shift Left by 1-31 bits.
LSRLogical Shift Right by 1-32 bits.
ASRArithmetic Shift Right by 1-32 bits.
RORRotate Right by 1-31 bits.
RRXRotate Right with Extend.

asm

    mov r0, r1	; r0 = r1

	mov r1, #12         ; r1 = 12;
	mov r0, r1, LSL #3	; r0 = r1 << 3 = 512
	mov r0, r1, LSR #3  ; r0 = r1 >> 3 = 8
	mov r0, r1, ASR #3  ; r0 = r1 >> 3 = 8 		不改写符号位
	mov r0, r1, ROR #3	; r1 = 0x80000001
	mov r0, r1, RRX  	; r0 = r1 >> 1 | 空位 = C

获取内存地址中的数据,需要使用LDR/STR操作符;

首先确定,RAM的地址范围;

打开simulator->Memory Configuration

RAM地址范围

可以得到RAM的地址0x00900000 –> 0x0097FFFF,

asm

ldr r0, =0x123		;; r0 = 0x123
ldr r1, =0x900000	;; r1 = 0x900000
str r0, [r1]		;; *((unsigned long *)r1) = r0;
mov r0, 0			;; r0 = 0
ldr r0, [r1]		;; r0 = *((unsigned long *)r1)

但是此时只能得到一些奇怪的数据,那如何确定程序是运行正常的?

assembly

;; 读取异常地址,看看是否会崩溃
;; 如果获取一个异常的地址,
;; 看看会发生什么?
ldr r1, =0x00980000
ldr r0, [r1]

程序立即崩溃, 我们的测试是正确的;

image-20221007163149155

assembly

LDR    R0,	[R1,#0X0F] ;; R0 = *(unsigned long *)(R1 + 0x0f)
LDR    R0,	[R1],#4	   ;; R0 = *(unsigned long *)(R1 + 0x04)
LDR    R0,	[R1,R2]	   ;; R0 = *(unsigned long *)(R1 + R2)

批量寻址来自于批量操作符STM/LDM,

assembly

LDMIA    R0,{R1,R2,R3,R4}
STMIA    R0,{R3-R5,R10}

assembly

LDMFD    SP!,{R1-R7,LR}
STMFD    SP!,{R1-R7,LR}

跳转指令可以向前后32M地址跳转 跳转为24位长有符号数据

  • B: 绝对跳转
  • BL: 带返回的跳转
  • BLX: 带返回和状态切换的跳转
  • BX: 状态切换的跳转

B(跳转) L(设置链接寄存器) X(切换arm/thumb状态)

跳转指令的详细解释: add pc, pc, #跳转地址

assembly

;; 跳转指令
	B label_jump_B
label_jump_B:
	mov pc, lr

;; 但是此时编译会报错,需要状态切换
BX label_jump_BX
	label_jump_BX:

	BL label_jump_BL
label_jump_BL:

	BLX label_jump_BLX
label_jump_BLX:
  • mov: 直接传送
  • mvn: 取反码传送

assembly

	mov r0, #12 ;; R0 = 0x0000000C
	mvn r1, #12 ;; R1 = 0xFFFFFFF3
  • cmp
  • cmn
  • tst
  • teq

assembly

	cmp r0, r1 ;; r0 - r1 ==> NZCV
	cmn r0, r1 ;; r0 + r1 ==> NZCV
	tst r0, r1 ;; r0 & r1 ==> NZCV

比较指令会影响到NZCV标志

N -> Negative 负数 Z -> Zero 零 C -> Carry 进位 V -> oVerflow 溢出

  • add
  • sub
  • rsb
  • adc
  • sbc
  • rsc

assembly

  • and
  • bic
  • eor
  • orr

assembly

  • mul
  • mla
  • smull
  • umull
  • umlal
  • clz
  • mrs: 状态寄存器到通用寄存器
  • msr: 通用寄存器到状态寄存器
  • ldr/str
  • ldm/stm

原子操作指令

  • swp
  • swpb
  • swi
  • bkpt
  • cdp

  • ldc

  • stc

  • mcr

  • mrc

16个NEON寄存器(128bit), Q0-Q15(同时也可以被视为32个64bit的寄存器,D0-D31)

  • 16个VFP寄存器(32bit),S0-S15

assembly

	SECTION .intvec:CODE:NOROOT (2)
	END

但是此时是无法进行编译的

assembly

.global _start
_start:      @汇编入口
loop:
	B loop
.end         @汇编程序结束
GCCarmasm描述信息
@;Comment
#&#0xAn immediate hex value
.ifIFDEF, IF条件编译
.elseELSE
.elseifELSEIF
.endifENDIF
.ltorgLTORG
``:OR:
&:AND:AND
«:SHL:Shift Left
»:SHR:Shift Right
.macroMACROStart macro definition
.endmENDMEnd macro definition
.includeINCLUDEGNU Assembler requires “filename”
.wordDCDA data word
.shortDCW
.longDCD
.byteDCB
.reqRN
.globalIMPORT, EXPORT
.equEQU

新建工程

image-20221007165810492

设置仿真

configure-project

构建仿真

debug-project

  • arm-none-eabi-gcc: 编译器
  • openocd: 调试器
  • qemu: 仿真器