嵌入式Linux应用开发(三)——汇编语言


前言

对于做Linux的应用开发,我们依旧需要会使用汇编语言。比如系统启动时的初始化,进出中断时的环境保护、恢复、对性能要求非常苛刻的函数等。都还是需要我们会使用汇编语言。对于汇编语言的讲述,下面我主要从ARM架构进行分析,然后再对汇编语言的指令,语法进行讲述。希望通过这个博客能让你对汇编语言有一个清晰的认识。


一、ARM架构

背景

相信大家都清楚平时我们使用的电脑是x86架构,使用的单片机(STM32F103)是ARM架构。但是你知道这两种架构的差别是什么吗?

CISC:一般我们所使用的电脑都是x86架构,而x86架构就是CISC(复杂指令集架构)
的一种。为什么叫复杂指令集架构呢?因为这个指令集(指令集:CPU执行的指令)采用64位来表示,且CISC指令表示动作多,操作复杂。但是指令的执行能力强,寻址方式多,操作CPU方便,极大的提高了CPU的效率。对于一个读写操作只需要通过一条指令来触发微程序即可实现,所以因为其高操作性而被广泛运用。

RISC:我们大部分所使用的单片机都是使用的ARM公司研发的ARM架构,所谓ARM架构就是精简指令集(RISC),因为他的指令采用32位,拥有指令长度固定,执行效率高的特点而被广泛使用。对于一个读写操作需要使用4条指令来完成,每一条指令都是直接操作寄存器,所以执行效率高,可实现的功能相应也就越少。

ARM内部寄存器

在ARM架构中,CPU内部有15个寄存器。
在这里插入图片描述其中R0~R12都是通用寄存器(一般用来存储数据或者地址,通用适用于所有功能)

R13表示的是栈指针,栈指针的功能是用来确定栈在内存中的位置

R14表示链接寄存器,也叫保存返回地址寄存器,在进行函数调用的时候,函数执行完后,我们需要返回主程序,就是通过在LR寄存器中保存原地址后,跳转回去的。

R15表示程序计数器,也叫PC指针,用于表示CPU下一个要执行的指令的地址。

注意:在M3/M4中还有一个(PSR)程序状态寄存器,用于记录当前程序的状态。

ARM汇编

在ARM架构中,又有3中指令集(均是精简指令集)

ARM指令集:32位指令,高效,但是太占空间

Thumb指令集:16位指令,节省空间

Thumb-2指令集:16位指令集和32位指令集混合编程(暂时只有Cortex—M系列)

注意:程序状态寄存器中有一位,名为“T”,它等于1的时候表示当前运行的是Thumb指令。


二、汇编指令

1.指令的分类

汇编指令的工作原理是通过对CPU发出指令来直接操作寄存器,所以这也是为什么汇编语言相比于其他高级语言执行效率更高的原因,因为他可以直接对寄存器进行操作,只需要进行汇编,不需要预处理,编译等操作。因此汇编指令分为以下5类

内存访问
数据处理
跳转指令
饱和运算
其他指令

立即数的概念

所谓立即数就是值可以在寄存器中直接存储的数据。比如0x12就是立即数,0x12345678就不是立即数。因为寄存器只能存储32位的数据,显然0x12345678使用32位没法表示,因此只能放在内存中,所以对于将数据0x12,就可以通过一条指令将数据写进寄存器,但是0x12345678就需要先把数据写到内存中,在通过把在内存中的地址的内容传给寄存器。

如何判断一个数是否是立即数

通过一个公式:立即数=某8位数 循环移位偶数位

伪指令 LDR 、ADR

伪指令的作用就是当我们想把某个数赋值给寄存器时,我们就可以使用伪指令,编译器会自动根据我们需要赋值的数据进行指令的替换,如果这个数是立即数,则就直接复制,如果不是立即数,便通过把这个值的地址的内容赋值给寄存器。

在这里插入图片描述ADR伪指令:
ADR表示的意思就是addres,地址的意思。就是用来读某个标号的地址
在这里插入图片描述

2.内存访问指令

使用到的软件

ARM汇编模拟器,通过(一)中给的链接,在该文档中的目录中即可下载安装,或者直接在网上下载即可
在这里插入图片描述

LDR、STR、LDM、STM、LSL

寄存器原则:低标号的寄存器对应低地址

LDR:Load Register(装在到寄存器,读取单个指令数据)

STR:Store Register(保存到寄存器,写单个指令数据到寄存器)

LDM:Load Multiple Register(一次性访问读取多个指令)

STM: Store Multiple Register(一次写多个数据)

LSL:表示左移

实验一代码

		MOV		R0,#0X20000
		MOV		R1,#0X10
		MOV		R2,#0X12
		STR		R2,[R0];将R2的值写到R0所指向的内存中
		STR		R2,[R0,#4];表示将R2的值写到R0的值加4所指向的内存中
		STR		R2,[R0,#8]!;表示将R2的值写到R0的值加8所指向的内存中,并反向更新R0的值
		STR		R2,[R0,R1];将R2的值写到R0加R1的值所指向的内存中
		STR		R2,[R0,R1,LSL #4];将R2的值写到R0的值加上R1左移4位的值所指向的内存中
		STR		R2,[R0],#0X20;将R2的值写到R0的值所指向的内存中后,R0进行更新等于加上20
		MOV		R2,#0X34;将R2寄存器赋值为34
		STR		R2,[R0];//将R2的值写道R0的值所指向的内存中
		LDR		R3,[R0],+R1,LSL #1;将R0的值所指向的内存的值读取到R3中后,将R0的值进行更新加上R1左移一位。

实验结果

在这里插入图片描述

实验二代码

		MOV		R1, #0X12
		MOV		R2, #0X34
		MOV		R3, #0X56
		MOV		R0,#0X20000
		STMIA	R0,{R1-R3};//将R1—R3的值写到,R0,R0+4,R0+8的值所指向的内存

实验结果

在这里插入图片描述

分析:

IA:表示计算后进行加法更新

IB:表示计算前进行加法更新

DA:表示计算后进行减法更新

DB:表示计算前进行减法更新

注意:一定是低寄存器对应低地址


数据处理指令

加法指令:ADD (实验一)

减法指令:SUB(实验二)

位操作:(实验三)
在这里插入图片描述
赋值指令:MOV

比较指令:CMP(实验四)
在这里插入图片描述

实验一

LDR		R1,=0X12
LDR		R2,=0X34
ADD		R1,R1,R2


		LDR		R1,=0X12
		LDR		R2,=0X34
		ADD		R1,R1,#0X12;//也可以加上一个立即数

实验二

		LDR		R1,=0X12
		LDR		R2,=0X1
		SUB		R1,R1,R2

		LDR		R1,=0X12
		LDR		R2,=0X1
		SUB		R1,R1,#0X1
		
		LDR		R1,=0X12
		LDR		R2,=0X1
		SUBS		R1,R1,#0X1;//S表示影响程序状态寄存器

实验三

		LDR		R1,=0X12
		LDR		R2,=0X1
		AND		R1,R1,#0X10;//AND表示与上这个数 
		
		LDR		R1,=0X12
		LDR		R2,=0X1
		BIC		R1,R1,#0X2;//表示清除第几位
		
		LDR		R1,=0X12
		LDR		R2,=0X1
		ORR		R1,R1,#0X10;//或上这个数

实验四

		LDR		R1,=0X12
		LDR		R2,=0X1
		CMP		R1,R2;//就表示相减的结果,是0,程序状态寄存器中的Z位就会是1
		
		LDR		R1,=0X12
		LDR		R2,=0X1
		TST		R1,R2;//表示相与的结果,如果是0,z位就会是1

实验结果

在这里插入图片描述


跳转指令

核心指令是B,BL

B: Branch ,跳转(实验一)
BL: Branch with Link,跳转前先把原地址保存在LR寄存器中(实验二)

实验一

		MOV		R0 ,#5
		
LOOP
		SUBS		R0 ,R0,#0X1
		BNE		LOOP
		MOV		R0 ,#0X1

实验二

		BL		Delay;跳转前先把原地址保留在LR寄存器中
		MOV		R1,#5
Delay
		MOV		R0,#0X10
LOOP
		SUBS		R0,R0,#1
		BNE		LOOP
		MOV		PC,LR

可使用BX指令,对thumb指令和ARM指令进行切换

其中BLX要比BL多一位状态表示

也可以直接给PC赋值

实验三

		ADR		LR ,Ret;//ADR伪指令,将Ret标号的地址赋值给LR寄存器,就是返回的地址
		ADR		PC ,Delay;//伪指令,将Delay标号的地址赋值给PC寄存器,所以直接跳转
Ret
		MOV		R1,#1
Delay
		MOV		R0,#0XF
LOOP
		SUBS		R0,R0,#1
		BNE		LOOP
		MOV		PC,LR;//将LR寄存器中的值赋值给PC指针,所以直接返回到Ret标号位置进行执行

总结

对于上面一些没有实验结果的代码,可以自行敲一遍,结果肯定是没有问题的,希望上面的内容对你有所帮助

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Jacky~~

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

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

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

打赏作者

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

抵扣说明:

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

余额充值