ARM汇编指令

一、指令

1. 寻址

多寄存器寻址
STMFD:保存至堆栈满递减,满:堆栈时刻都是满的,所以先减再入栈,入栈之后指针还是指向有效数据
至于多寄存器的出栈入栈顺序需要格外注意:

STMFD SP!, {R1-R12}

堆栈满递减,向下生长(下面是低地址),那么是先压进去R1呢还是先压进去R12呢,根据实验结果看,是先压R12。
重点:多寄存寻址与寄存器书写顺序无关,低地址对应编号低的寄存器,高地址对应编号高的寄存器。如果是压栈的话,无论是递增还是递减,都是低地址存编号低的寄存器。

2. 数据处理

ORR
逻辑或指令
BIC 清除寄存器某一位

MRS R0, CPSR
BIC R0, R0, #0x80 ;开IRQ中断
MSR CPSR_cxsf, R0

先从CPSR中读取数值,然后使用BIC清除掉第7位,第7位控制IRQ中断,第六位控制FIQ中断,第五位控制Thumb指令。最后使用MSR存回去,注意必须指定MSR存回的区域,用小写字母代替(必须小写)c:控制域;f:标志位域;x、s:arm9没用到。
立即寻址有效数问题

MOV R0, #0x18   ; #0x18是立即数
LDR R1, =0x20026 ; #0x20026不是立即数,使用伪指令

MSR CPSR_问题

错误:

MSR CPSR_C, #0xd0 ;1101 0000

正确:

MSR CPSR_c, #0xd0 ;1101 0000
MSR cpsr_c, #0xd0 ;1101 0000

LDR指令与LDR伪指令
1.

LDR R0, =IOSET
LDR R1, =0x00500500
STR R1, [R0]

在汇编编译器处理源程序时,如果该常数没有超过MOV可以操作的范围,则LDR指令被一条MOV替代,否则,该常数将被放在最近的一个文字池内,同时,本指令被一条基于PC的加载指令LDR替代。
从PC到文字池的偏移量必须小于4KB。
于ARM指令的LDR相比,伪指令的LDR有参数“=”号。
2.又发现一个事情

LDR SP, und_stack
LDR SP, =und_stack

usr_stack DCD usr_stack_space+(usr_stack_length-1)*4

不一样!!!
LDR SP, und_stack 是直接把und_stack的数值赋给了SP 助记: SP = und_stack
LDR SP, =und_stack 是把und_stack的地址赋给了SP 助记: SP = &und_stack

LDR和LDM、STR和STM
LDR Rd, <地址> ;从右到左读取
STR Rd, <地址> ;从左到右存储

LDMIA R0, {R4-R11} ;从左往右读取
STMIA R0, {R4-R11} ;从右往左存储

注意:LDR是寄存器在地址左边、LDM是地址在寄存器左边。
包含变量的定义的程序架构
下面程序报错,Entry point (0x00008000) does not point to an instruction.

	entry
	code32
dataBuf DCD 11, -2, 35, 47, 96, 63, 128, -23
start

改为

	entry
	code32
	B start
dataBuf DCD 11, -2, 35, 47, 96, 63, 128, -23
start

或者改为

	AREA init, code, readonly
dataBuf DCD 1, 2, 3, 4, 5, 6, 7, 8
	entry
	code32

或者改为

	B .
	AREA Datapool, DATA, READWRITE
dataBuf DCD 1, 2, 3, 4, 5, 6, 7, 8
	END

数组的定义与引用

	B start
dataBuf DCD 1, 2, 3
start
	LDR R0, =dataBuf

应用的时候注意使用 =

数组的循环遍历

loop
	LDR R4, [R0, R3] ;读取数组的值
	CMP R4, R1
	MOVGT R1, R4 ;如果R4大于R1,那么R4的值存储到R1中
	CMP R4, R2
	MOVLT R2, R4 ;如果R4小于R2,那么R4的值存储到R2中

	ADD R3, R3, #4 ;每次地址偏移的步长是4
	CMP R3, #32 ;遍历8个元素,需要偏移32
	BNE loop ;不等于0接着循环
	STR R1, [R0]
	B .

注意:步进的控制。DCD是字对齐,DCB是字节

二、伪指令

1. 数据定义

任何语言都少不了数据定义,arm汇编中除了我们接触到的写进代码中的立即数寻址,算是一种数据,还有LDR伪指令算是一种数据。正常的数据定义该如何做?

指令指令语法指令解释
DCBstring DCB “Hello world”字节分配内存单元
DCWdata1 DCW 0x2a*0x2a半字分配内存单元
DCWU非半字对准
DCDdata1 DCD 4, 5, 6字分配内存单元(四个字节)
DCDU非字对准
DCFDflo1 DCFD 2E115, -5E-7双精度浮点数分配内存单元
DCFDUflo1 DCFD 2E115, -5E-7非字对准(两个字)
DCFSflo1 DCFD 2E5, -5E-7单精度浮点数分配内存单元
DCFSUflo1 DCFD 2E5, -5E-7非字对准(一个字)
DCQdata1 DCD 4, 5, 6双字分配内存单元
DCQU非字对准(两个字)

EQU 等效的意思
名称 | EQU | 表达式 | {, 类型}
这个特别像宏定义,汇编之后也没有代码生成,“名称”的使用和被等效的东西的使用方法一模一样。

	ENTRY
	CODE32
x EQU 45
y EQU 64
stack_top EQU 0x1000
start
	MOV SP, #stack_top
	MOV R0, #x

在这里插入图片描述
可以看出来语句初始地址还是0x8000,说明x、y、stack_top定义没有生成代码。其实就是给汇编器做替代的。
LTORG声明文字池
LTORG ;声明文字池,此地址存储0x12345678,放的位置有讲究,不能让处理器把文字池的数据当作指令执行。通常放在无条件跳转指令后面,避免PC指针指向这个区域。
END是与什么对应的?
好像end并不和什么对应。END伪指令用于指示汇编编译器源文件已结束,每一个汇编源文件均要有一个END伪指令,指示本源程序结束。
NOP
空操作伪指令,并且占用4字节的代码空间,中断向量表的定义时就可以用它来占位。

start
	B Reset_Handler
Undefined_Handler B Undefined_Handler
SWI_Handler B SWT_Handler
Prefetch_Handler B Prefetch_Handler
Abort_Handler B Abort_Handler
	NOP ;空操作伪指令,占用32位代码空间
IRQ_Handler B IRQ_Handler
FIQ_Handler B FIQ_Handler

程序结构

循环读取数组,并且修改后存储回去

发现一个问题,就是改不回去,有点像rom只读一样,但是当数组定义的位置不同,结果不同。
只有

	AREA Init, CODE, READONLY
initData DCD 1, 2, 3, 4, 5, 6, 7, 8
	ENTRY

是可以改动的。

三、注意

码格式问题
新的一行的开头,除了标号,别的字段前需要加空格或tab。
AXD仿真程序复位
没有复位按钮,但是有重新加载image的按钮,第二行左边第三个按钮。

报错代码
错误:

	AREA init CODE, READONLY
	ENTRY
	CODE32
start
	MOV SP, #0x800
	B .
	END

正确:


	AREA init, CODE, READONLY
	ENTRY
	CODE32

start
	MOV SP, #0X800
	B .
	end

原因:第一行少了个逗号。。。。
报错提示也就那样吧,还是自己淌水吧。
MSR中CPSR域的问题:字母大小写。。。。
报错:

MSR CPSR_C,#0xd2 

正确:

MSR CPSR_c,#0xd2 

协处理器问题:字母大小写。。。。
报错:

MRC P15, 0, R0, C1, C0, 0
ORR R0, R0, #0xc0000000 ;或1101b
MCR P15, 0, R0, C1, C0, 0

正确:

MRC p15, 0, R0, c1, c0, 0
ORR R0, R0, #0xc0000000 ;或1101b
MCR p15, 0, R0, c1, c0, 0

p和c必须小写!

SWI后 PC指针的设置
由于ARM采用三级流水线结构,因此,当SWI和未定义指令异常中断产生时,程序计数器PC的值还没有更新,它指向当前指令后面第2条指令(对于ARM指令,它指向当前指令地址加8个字节的位置;对于Thumb指令,它指向当前指令地址加4个字节的位置)。这就是为什么当SWI和未定义指令异常中断发生时,处理器将(PC-4)保存到异常模式下的寄存器lr_mode中,这时(PC-4)即指向当前指令的下一条指令

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

匿名匿名匿名11

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值