基础汇编语言编程

本文介绍了ARM汇编语言的基本概念,包括新建工程、环境设置以及数据处理指令如加、减、乘。通过实例展示了立即数的限制,解释了为何不能直接用`MOV`指令存入0x12345678,并探讨了UART通信中数据位的规定及其影响。此外,还讨论了CPSR寄存器的NZCV位,内存读写操作如`STR`和`LDR`,以及不同类型的索引操作。最后,提到了批量寄存器操作。
摘要由CSDN通过智能技术生成

目录

什么是汇编语言?

工程搭建

新建工程

环境设置

 测试是否成功

 正式学习汇编语言

数据处理指令

填充,加,减,乘

 思考:我们可以看到R0寄存器可以存放8位十六进制数,那么0x12345678能不能用mov存入?

与,或,异或,左移,右移

思考:UART通信过程中为什么数据位规定8-9位?

思考:如果规定12或者更多可以吗?有什么影响?

CPSR寄存器的(NZCV位)

 N位(负标记位)检测

 思考:为什么N位为什么没有置为1?

 Z位(0标记位)和C(进位和借位标记)

 存储位数过多数据存储原理(ADC)

 对内存的读写(STR,LDR)

回到最初的问题:如何赋值0x12345678?

对内存读写基础操作

前索引

后索引

自动索引(前后索引)

 批量寄存器操作


注:本文章记录自己现阶段学到的基础汇编语言编程

什么是汇编语言?

汇编语言是一种低级程序设计语言,用于编写计算机程序。它是与特定计算机体系结构相关的,通过使用符号代表机器指令数据,以便于人们理解和编写程序。

由于汇编语言是与特定体系结构相关的,所以每种计算机体系结构都有自己的汇编语言。常见的汇编语言包括x86(用于大多数个人电脑)、ARM(用于移动设备和嵌入式系统)等。本文主要记录基础ARM汇编语言。

编写汇编语言程序需要对计算机体系结构和指令集有深入的了解,并且编写的程序可以直接在相应的计算机上运行。汇编语言程序通常用于对性能要求非常高或需要直接访问硬件的应用,如操作系统、驱动程序、嵌入式系统等。

工程搭建

新建工程

 

环境设置

 

 测试是否成功

输入下方汇编代码测试

	AREA RESET,CODE,READONLY
ENTER
	MOV R1,#1
 END

 正式学习汇编语言

数据处理指令对数据进行逻辑、算数运算

在汇编语言中;是注释的意思

	AREA RESET,CODE,READONLY 
	;AREA	指定代码属性
	;RESET	代码片段名称
	;CODE	存放代码
	;READONLY	只读
ENTER	;顶头写的我们称为标号 ENTER是程序入口
	MOV R1,#1	;前面有空格的我们称为指令
 END    ;END是结尾

数据处理指令

填充,加,减,乘

	AREA RESET,CODE,READONLY 
ENTER	
	MOV R0,#1	;将1值填充到R0寄存器
	MOV R1,#2	;将2值填充到R1寄存器
	ADD R2,R1,R0	;R2寄存器值=R1+R0
	SUB R3,R1,R0	;R3=R1-R0
	MUL R4,R1,R0	;R4=R1*R0
 END

 

 上面演示了基础操作,主要说下第二个界面

 我们看看上面指令最终结果,对应寄存器存储了对应的运算结果

 思考:我们可以看到R0寄存器可以存放8位十六进制数,那么0x12345678能不能用mov存入?

	AREA RESET,CODE,READONLY 
ENTER	
	MOV R0,#0x12345678	;将0x12345678值填充到R0寄存器
 END

 程序报错了

ARM.S(3): error: A1510E: Immediate 0x12345678 cannot be represented by 0-255 and a rotation

 ARM.S(3): error: A1510E: Immediate 0x12345678不能用0-255

这里引入了立即数概念

立即数(Immediate value)是在汇编语言中表示常数或立即数据的一种方式。它是直接包含在指令中的固定数值,而不是通过寄存器或内存引用获取。

通过测试我们得到当前操作立即数范围是0-255,255后面都是离散的。

那么如何赋值0x12345678?后面会讲解。

与,或,异或,左移,右移

	AREA RESET,CODE,READONLY 
ENTER	
	MOV R1,#1	;将1值填充到R0寄存器
	AND R2,R1,#0 ;R2=R1&0	与
	ORR R3,R2,#1 ;R3=R2|1	或
	EOR R3,R1,#1 ;R3=R1^1	异或
	LSR R3,R2,R1 ;R3=R2<<R1
	LSL R3,R2,R1 ;R3=R2>>R1
 END

思考:UART通信过程中为什么数据位规定8-9位?

  • 8位可以表示256个不同的数值,足够用于表示大部分常见的字符、数字和符号
  • UART通信的具体配置(包括数据位、停止位、波特率等)应该根据通信双方的协商和需求进行设置,以确保正确的数据传输和解析,8位常用。

思考:如果规定12或者更多可以吗?有什么影响?

12位是可行的,但会存在一些影响和限制

  • 兼容性问题:UART通信是由双方协商决定的,两个设备必须都支持12位才行
  • 增加传输开销:增加数据位数量会导致数据字节传输开销增加
  • 设备复杂性增加:位数越多,硬件设计和软件设计实现复杂
  • 干扰和误差率增加:较长的数据位序列更容易受到噪声和干扰的影响

CPSR寄存器的(NZCV位)

 N位(负标记位)检测

	AREA RESET,CODE,READONLY 
ENTER
	;N位负标记位
	MOV R0,#1	;将1值填充到R0寄存器
	MOV R1,#2	;将2值填充到R1寄存器
	SUB R2,R0,R1	;R2=R0-R1
 END

 思考:为什么N位为什么没有置为1?

默认情况下数据运算不会对条件位(NZCV)产生影响,我们可以在指令后添加后缀 'S'
	AREA RESET,CODE,READONLY 
ENTER
	;N位负标记位
	MOV R0,#1	;将1值填充到R0寄存器
	MOV R1,#2	;将2值填充到R1寄存器
	SUBS R2,R0,R1	;R2=R0-R1
 END

 Z位(0标记位)和C(进位和借位标记)

	AREA RESET,CODE,READONLY 
ENTER
	;N位负标记位
	MOV R0,#1	;将1值填充到R0寄存器
	MOV R1,#1	;将2值填充到R1寄存器
	SUBS R2,R0,R1	;R2=R0-R1
 END

 

	AREA RESET,CODE,READONLY 
ENTER
	;N位负标记位
	MOV R0,#0xFFFFFFFF	;将0xFFFFFFFF值填充到R0寄存器
	MOV R1,#3	;将3值填充到R1寄存器
	ADDS R2,R0,R1	;R2=R0+R1
 END

 存储位数过多数据存储原理(ADC)

假设有两个数据,怎么进行存储? 

第一个数        0x00000001 FFFFFFFF

第二个数        0x00000005 00000002

我们可以:
第一个数的低32位放到R1,高32bit放R2

第二个数的低32位放R3,高32bit放R4

低加低高加高 运算结构的低32bit放R5,高32bit放R6

	AREA RESET,CODE,READONLY 
ENTER
	;N位负标记位
	MOV R1,#0xFFFFFFFF	;NUM1低32位放R1
	MOV R2,#0x00000001	;NUM1高32位放R2
	MOV R3,#0x00000002	;NUM2低32位放R3
	MOV R4,#0x00000005	;NUM2高32位放R4
	ADDS R5,R1,R3	;R5=R1+R3	存放低位
	ADDS R6,R2,R4	;R6=R2+R4	存放高位
 END

 上面的代码能达到我们想要的效果吗?

 正确操作是添加C特殊的标志位,使用ADC进行运算

	AREA RESET,CODE,READONLY 
ENTER
	;N位负标记位
	MOV R1,#0xFFFFFFFF	;NUM1低32位放R1
	MOV R2,#0x00000001	;NUM1高32位放R2
	MOV R3,#0x00000002	;NUM2低32位放R3
	MOV R4,#0x00000005	;NUM2高32位放R4
	ADDS R5,R1,R3	;R5=R1+R3	存放低位
	ADC R6,R2,R4	;R6=R2+R4+'C'	存放高位
 END

 对内存的读写(STR,LDR)

回到最初的问题:如何赋值0x12345678?

使用LDR命令就能完成赋值操作

	AREA RESET,CODE,READONLY 
ENTER
	LDR R1,=0x12345678
 END

 但是R5此时却变为了0x07800000

R5 变为了 0x07800000,而不是 R1。这可能是因为汇编器在分配常量池地址时,将立即数 0x12345678 分配到了常量池的偏移量为 0x07800000 的位置,并将该地址加载到了 R5 寄存器中。

对内存读写基础操作

	AREA RESET,CODE,READONLY 
ENTER
	MOV R0,#0x40000000 ;设置R0值为0x40000000
	MOV R1,#0xFF
	STR R1,[R0]		;将R1值存放到地址0x40000000
	LDR R2,[R0]		;将地址0x40000000的值取出放到R2
 END

前索引

	AREA RESET,CODE,READONLY 
ENTER
	MOV R0,#0x40000000 ;设置R0值为0x40000000
	MOV R1,#0xFF	   ;设置R1值为0xFF
	STR R1,[R0,#4]	   ;将R1值存放到地址0x40000004
 END

 

后索引

	AREA RESET,CODE,READONLY 
ENTER
	MOV R0,#0x40000000 ;设置R0值为0x40000000
	MOV R1,#0xFF	   ;设置R1值为0xFF
	STR R1,[R0],#4	   
	;将R1值存放到地址0x40000000
	;RO地址变为Ox40000004
 END

自动索引(前后索引)

	AREA RESET,CODE,READONLY 
ENTER
	MOV R0,#0x40000000 ;设置R0值为0x40000000
	MOV R1,#0xFF	   ;设置R1值为0xFF
	STR R1,[R0,#4]!	   
	;将R1值存放到地址0x40000004
	;RO地址变为Ox40000004
 END

 批量寄存器操作

	AREA RESET,CODE,READONLY 
ENTER
	MOV R0,#0x40000000
	MOV R1,#1
	MOV R2,#2
	MOV R3,#3
	MOV R4,#4
	MOV R5,#5
	STM R0,{R1-R5}
	LDM R0,{R6-R10}
 END

	AREA RESET,CODE,READONLY 
ENTER
	;空增
	MOV R0,#0x40000000
	MOV R1,#1
	MOV R2,#2
	MOV R3,#3
	MOV R4,#4
	MOV R5,#5
	STMIA R0!,{R1-R5}
	;满增
	MOV R0,#0x40000000
	MOV R1,#1
	MOV R2,#2
	MOV R3,#3
	MOV R4,#4
	MOV R5,#5
	STMIB R0!,{R1-R5}
	
	;空减
	MOV R0,#0x4000000C
	MOV R1,#1
	MOV R2,#2
	MOV R3,#3
	MOV R4,#4
	MOV R5,#5
	STMDA R0!,{R1-R5}
	;满减
	MOV R0,#0x4000000C
	MOV R1,#1
	MOV R2,#2
	MOV R3,#3
	MOV R4,#4
	MOV R5,#5
	STMDB R0!,{R1-R5}
 END

 上述四段代码分开测试能得到结果

 

  • 0
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值