一、简单的汇编程序
1.创建一个工程
1.打开Kiel,project->new μvison Project;
2.然后选择自己保存文件的路径;
3.之后选择自己的芯片、环境、启动文件,如下图;
这里我选择的芯片是STM32F03RC。
二、添加文件
1.鼠标右键单击Source Group 1,选择Add New Item to Group
2.选择 Asm File (.s) ,设置源文件的名称(此处源文件命名为TEST),点击Add
3.之后写入代码
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
4.之后根据自己的实际情况进行选择自己的仿真器及模式
此处是编译后的信息。
四、结果分析
此处为编译后的hex文件。
第一行内容含义
0x02
该行数据中有两个数据
0x00 0x00
本行数据的起始地址位
0x04
用来标识扩展线性地址的记录
该字节还可以是其他值,下面是其他值的含义
00
:用来记录数据,HEX文件的大部分记录都是数据记录
01
:用来标识文件结束,放在文件的最后,标识HEX文件的结尾
02
:用来标识扩展段地址的记录
03
:开始段地址记录
05
:开始线性地址记录
0x08 0x00
该行两个字节的数据
数据类型是 04 ,即该行记录的是一个拓展地址(0x08 0x00 是地址信息,用法是将该地址(0x0800<<16) 后作为基地址
0xF2
校验和,校验和= 0x100 – 累加和
五、用汇编程序完成 每间隔1秒钟闪烁一次LED的程序
创建一个新工程,步骤跟上面步骤基本一致,但不需要添加启动代码(startup,core)。
写入代码:
LED0 EQU 0x40011004;定义引脚PC2
RCC_APB2ENR EQU 0x40021018;配置RCC寄存器,时钟
GPIOC_CRL EQU 0x40011000;配置CRL寄存器
Stack_Size EQU 0x00000400;栈的大小
;分配一个STACK段,该段不初始化,可读写,按8字节对齐。分配一个大小为Stack_Size的存储空间,并使栈顶的地址为__initial_sp。
AREA STACK, NOINIT, READWRITE, ALIGN=3;NOINIT: = NO Init,不初始化。READWRITE : 可读,可写。ALIGN =3 : 2^3 对齐,即8字节对齐。
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;BL:带链接的跳转指令。当使用该指令跳转时,当前地址(PC)会自动送入LR寄存器
MainLoop BL LED_ON
BL Delay
BL LED_OFF
BL Delay
B MainLoop;B:无条件跳转。
LED_Init;LED初始化
PUSH {R0,R1, LR};R0,R1,LR中的值放入堆栈
LDR R0,=RCC_APB2ENR;LDR是把地址装载到寄存器中(比如R0)。
ORR R0,R0,#0x04;ORR 按位或操作,将将R0的第二位置1,其他位不变
LDR R1,=RCC_APB2ENR
STR R0,[R1];STR是把值存储到寄存器所指的地址中。
LDR R0,=GPIOC_CRL
BIC R0,R0,#0x0F;BIC 先把立即数取反,再按位与
LDR R1,=GPIOC_CRL
STR R0,[R1]
LDR R0,=GPIOC_CRL
ORR R0,R0,#0x03
LDR R1,=GPIOC_CRL
STR R0,[R1]
;将PC2置1
MOV R0,#1
LDR R1,=LED0
STR R0,[R1]
POP {R0,R1,PC};将栈中之前存的R0,R1,LR的值返还给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}
; NOP
END
AREA命令
:AREA 命令指示汇编器汇编一个新的代码段或数据段。段是独立的、指定的、不可见的代码或数据块,它们由链接器处理;
SPACE命令
:SPACE 命令保留一个用零填充的存储器块;
ENTRY命令
:声明整个程式的入口点,入口点有且仅有一个;
六、总结
在有别人的成果下,也能做出来结果,但自己独自完全不会,缺少兴趣,也缺少耐心,总之,还得加油。