基于stm32f103的MDK汇编介绍

一、ARM汇编语法简介

汇编语言是一种底层的语言,需要依赖硬件进行编写,基本换个硬件程序就需要重新编写,其实在stm32的C语言在机器执行时也要被转换为汇编语言再转换为机器代码执行。汇编语言与其他高级语言不同的地方在于,对数据或寄存器的操作是通过各种指令完成的,主要有跳转指令数据处理指令程序状态寄存器(PSR)处理指令加载/存储指令协处理器指令异常产生指令6大指令,常用指令集的介绍与使用可参考以下文章:
ARM汇编指令集
ARM汇编指令集汇总

二、MDK创建汇编工程

1、汇编工程的建立与C语言工程的建立有所不同,我们这里新建一个汇编工程,完成对一个汇编文件的编写及调试,keil也可执行多文件的汇编编译调试,具体方法参考Keil 汇编asm/A51多个文件

2、keil创建工程

(1)选择保存路径时尽量不要太深,名字不包含中文,切记不要直接丢桌面,放在文件夹里。
在这里插入图片描述
(2)选择芯片类型
在这里插入图片描述
(3)配置运行环境(如果自己的程序中写入了启动文件的内容则不需要添加startup
在这里插入图片描述
(4)添加源文件
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
工程创建完成。

三、编译测试及输出解释

1、测试代码
代码实现将寄存器r5、r6、r7、r8的值设置为0x00000005``0x00000006``0x00000007``0x00000008

 AREA MYDATA, DATA
	
 AREA MYCODE, CODE
	ENTRY
	EXPORT __main

__main
	MOV R0, #10
	MOV R1, #11
	MOV R2, #12
	MOV R3, #13
	;LDR R0, =func01

	BL	func01
	;LDR R1, =func02
	BL	func02
	
	BL 	func03
	LDR LR, =func01
	LDR PC, =func03
	B .
		
func01
	MOV R5, #05
	BX LR
	
func02
	MOV R6, #06
	BX LR
	
func03
	MOV R7, #07
	MOV R8, #08	
	BX LR

2、编译Debug调试查看寄存器地址
(1)编译结果无误则工程配置正确
在这里插入图片描述
(2)调试查看
在这里插入图片描述
(3)先运行程序,然后停止。
在这里插入图片描述

(4)在func01执行处设置断点
在这里插入图片描述(5)运行代码后,r5的值没有改变。
在这里插入图片描述
(6)取消断点后,运行程序,寄存器的值发生改变,且与程序设定一样。
在这里插入图片描述
3、输出hex文件解释
(1)设置工程输出hex文件
在这里插入图片描述
(2)hex文件在工程目录中,以文本打开。
在这里插入图片描述
第一行的数据即为,0x02、0x00、0x00、0x04、0x08、0x00、0xf2
第一个字节 0x02表示本行数据的长度;
第二、三字节 0x00 0x00表示本行数据的起始地址;
第四字节 0x04表示数据类型,数据类型有:0x000x010x020x030x040x05
00 Data Rrecord:用来记录数据,HEX文件的大部分记录都是数据记录
01 End of File Record: 用来标识文件结束,放在文件的最后,标识HEX文件的结尾

02 Extended Segment Address Record: 用来标识扩展段地址的记录

03 Start Segment Address Record:开始段地址记录

04 Extended Linear Address Record: 用来标识扩展线性地址的记录

05 Start Linear Address Record:开始线性地址记录

第五、六字节是数据,0x08 0x00

5.最后一个字节 0xf2为校验和。

校验和的算法为:计算 0xf2前所有16进制码的累加和(不计进位),检验和 = 0x100 - 累加和
‘04’ ‘05’,都是用来提供地址信息的。每次碰到这2个记录的时候,都可以根据记录计算出一个“基”地址。对于后面的数据记录,计算地址的时候,都是以这些“基”地址为基础的。

HEX文件都是由记录(RECORD)组成的。在HEX文件里面,每一行代表一个记录。记录的基本格式为:
:020000040800F2
:1000000048B6002085010008B1450008252B0108ED
:10001000B9450008C1450008C945000800000000B6
:00000001FF

四、简单的汇编点灯程序

1、程序中包含了启动文件内容,新建工程不添加启动文件
在这里插入图片描述
2、测试代码

LED0 EQU 0x42218194 ;LED0 (PB5)的bit-bond地址
RCC_APB2ENR EQU 0x40021018
GPIOB_CRL EQU 0x40010C00

Stack_Size      EQU     0x00000400

                AREA    STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem       SPACE   Stack_Size
__initial_sp

                AREA    RESET, DATA, READONLY

__Vectors       DCD     __initial_sp               ; Top of Stack
                DCD     Reset_Handler              ; Reset Handler
                    
                    
                AREA    |.text|, CODE, READONLY
                    
                THUMB
                REQUIRE8
                PRESERVE8
                    
                ENTRY
Reset_Handler 
                BL LED_Init
MainLoop        BL LED_ON
                BL Delay
                BL LED_OFF
                BL Delay
                
                B MainLoop
             
LED_Init
                PUSH {R0,R1, LR}
                
                LDR R0,=RCC_APB2ENR
                ORR R0,R0,#0x08		;使能GPIOB
                LDR R1,=RCC_APB2ENR
                STR R0,[R1]
                
                LDR R0,=GPIOB_CRL
                BIC R0,R0,#0XFF0FFFFF	;配置为模拟输入
                LDR R1,=GPIOB_CRL
                STR R0,[R1]
                
                LDR R0,=GPIOB_CRL
                ORR R0,R0,#0X00300000	;推挽输出
                LDR R1,=GPIOB_CRL
                STR R0,[R1]
                
                MOV R0,#1 
                LDR R1,=LED0
                STR R0,[R1]
             
                POP {R0,R1,PC}

             
LED_ON
                PUSH {R0,R1, LR}    
                
                MOV R0,#0 
                LDR R1,=LED0
                STR R0,[R1]
             
                POP {R0,R1,PC}
             
LED_OFF
                PUSH {R0,R1, LR}    
                
                MOV R0,#1 
                LDR R1,=LED0
                STR R0,[R1]
             
                POP {R0,R1,PC}             
             
Delay
                PUSH {R0,R1, LR}
                
                MOVS R0,#0
                MOVS R1,#0
                MOVS R2,#0
                
DelayLoop0        
                ADDS R0,R0,#1

                CMP R0,#330
                BCC DelayLoop0
                
                MOVS R0,#0
                ADDS R1,R1,#1
                CMP R1,#330
                BCC DelayLoop0

                MOVS R0,#0
                MOVS R1,#0
                ADDS R2,R2,#1
                CMP R2,#15
                BCC DelayLoop0
                
                POP {R0,R1,PC}    

                END

添加新的汇编文件,放入以上代码,编译下载。
3、代码简介
(1)预定义
在这里插入图片描述

每个需要用到的寄存器地址定义一个名字,类似于C语言的#define。bit-bond地址可查询标准库的sys.h文件中的计算方法,RCC和GPIO的地址是固定的,可从STM32的手册查询,或者根据ST官方的库文件查找计算。
(2)分配栈空间

在这里插入图片描述
(3)分配向量表
在这里插入图片描述
(4)开始代码段


通知汇编器,开始代码段。

在这里插入图片描述
这段的意思是,汇编器支持THUMB指令,代码段按8字节对齐。

ENTRY命令:声明整个程式的入口点,入口点有且仅有一个。
(5)程序运行

1、BL:带链接的跳转指令。当使用该指令跳转时,当前地址(PC)会自动送入LR寄存器。
2、B:无条件跳转。
3、PUSH和POP:可以看到,所有的子程序都是由PUSH和POP包起来的。PUSH {R0,R1, LR}的意思即把R0,R1,LR中的值放入堆栈中。由于主程式中使用BL跳转指令,所以LR中的值实际上就是当前PC的值。而POP {R0,R1,PC}的意思即是将栈中之前存的R0,R1,LR的值返还给R0,R1,PC。这样就完成了子程序的返回。
4、LDR和STR:寄存器的装载和存储指令。
LDR是把地址装载到寄存器中(比如R0)。
STR是把值存储到寄存器所指的地址中。
5、ORR和BIC:
ORR 按位或操作。ORR R0,R0,#0x04意思即将R0中的数或上0x04,再将结果送往R0中。实际意思就是将R0的第二位置1,其他位不变。
BIC 先把立即数取反,再按位与。
6、CMP和BCC:CMP是比较两个数,相等或大于则将标志位C置位,否则将C清零。BCC是个组合指令,实际为B+CC,意思是如果C=0则跳转。
CMP R2,#15; 计算R2-15的值,若是R2<15,则C=0;若是R2>=15,则C=1。
BCC DelayLoop0;若是C=0,则跳到DelayLoop0,若是c=1,则不跳转。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值