嵌入式作业2.1 汇编练习
原始参考代码(main.s)#
汇编代码:
//=====================================================================
//文件名称:main.s
//功能概要:汇编编程调用GPIO构件控制小灯闪烁(利用printf输出提示信息)
//版权所有:SD-ARM(sumcu.suda.edu.cn)
//版本更新:20180810-20191018
//=====================================================================
.include "include.inc" //头文件中主要定义了程序中需要使用到的一些常量
//(0)数据段与代码段的定义
//(0.1)定义数据存储data段开始,实际数据存储在RAM中
.section .data
//(0.1.1)定义需要输出的字符串,标号即为字符串首地址,\0为字符串结束标志
hello_information: //字符串标号
.ascii "-------------------------------------------------------\n"
.ascii "金葫芦提示: \n"
.ascii "1、本程序用来示范如何输出指令所在flash单元的地址以及指令 \n"
.ascii "所对应的机器码。 \n"
.ascii "2、Debug文件夹中的.lst文件可搜索汇编指令找到对应的机器码。\n"
.ascii "3、printf函数可根据输出格式输出参数的值。 \n"
.ascii "------------------------------------------------------\n\0"
data_format:
.ascii "%d\n\0" //printf使用的数据格式控制符
data_format1:
.ascii "%08x:%02x\n\0" //printf使用的数据格式控制符,其中8表示输出位数,
//0表示将输出的前面补上0,直到占满指定列宽为止
light_show1:
.ascii "LIGHT_BLUE:ON--\n\0" //灯亮状态提示
light_show2:
.ascii "LIGHT_BLUE:OFF--\n\0" //灯暗状态提示
light_show3:
.ascii "闪烁次数mLightCount=\0" //闪烁次数提示
//(0.1.2)定义变量
.align 4 //.word格式四字节对齐
mMainLoopCount: //定义主循环次数变量
.word 0
mFlag: //定义灯的状态标志,1为亮,0为暗
.byte 'A'
.align 4
mLightCount:
.word 0
//(0.2)定义代码存储text段开始,实际代码存储在Flash中
.section .text
.syntax unified //指示下方指令为ARM和thumb通用格式
.thumb //Thumb指令集
.type main function //声明main为函数类型
.global main //将main定义成全局函数,便于芯片初始化之后调用
.align 2 //指令和数据采用2字节对齐,兼容Thumb指令集
//--------------------------------------------------------------------
//main.c使用的内部函数声明处
//--------------------------------------------------------------------
//主函数,一般情况下可以认为程序从此开始运行(实际上有启动过程,参见书稿)
main:
//(1)======启动部分(开头)主循环前的初始化工作======================
//(1.1)声明main函数使用的局部变量
//(1.2)【不变】关总中断
cpsid i
//(1.3)给主函数使用的局部变量赋初值
//(1.4)给全局变量赋初值
//(1.5)用户外设模块初始化
// 初始化蓝灯, r0、r1、r2是gpio_init的入口参数
ldr r0,=LIGHT_BLUE //r0指明端口和引脚(用=,因常量>=256,需用ldr)
mov r1,#GPIO_OUTPUT //r1指明引脚方向为输出
mov r2,#LIGHT_OFF //r2指明引脚的初始状态为亮
bl gpio_init //调用gpio初始化函数
// 初始化串口UART_User1
mov r0,#UART_User //串口号
ldr r1,=UART_BAUD //波特率
bl uart_init //调用uart初始化函数
//(1.6)使能模块中断
mov r0,#UART_User //串口号
bl uart_enable_re_int //调用uart中断使能函数
//(1.7)【不变】开总中断
cpsie i
//显示hello_information定义的字符串
ldr r0,=hello_information //待显示字符串首地址
bl printf //调用printf显示字符串
//bl . //在此打桩(.表示当前地址),理解发光二极管为何亮起来了?
//(1)======启动部分(结尾)=======================================
//(2)======主循环部分(开头)=====================================
main_loop: //主循环标签(开头)
//(2.1)主循环次数变量mMainLoopCount+1
ldr r2,=mMainLoopCount //r2←mMainLoopCount的地址
ldr r1, [r2]
add r1,#1
str r1,[r2]
//(2.2)未达到主循环次数设定值,继续循环
ldr r2,=MainLoopNUM
cmp r1,r2
blO main_loop //未达到,继续循环
//(2.3)达到主循环次数设定值,执行下列语句,进行灯的亮暗处理
//测试代码部分[理解机器码存储]
Label:
MOV R0,#0xDE //立即数范围为0x00~0xFF
ldr r0,=data_format1 //输出格式送r0
ldr r1,=Label //r1中是Label地址
ldrb r2,[r1] //r2中是Label地址中的数据
bl printf
ldr r0,=data_format1 //输出格式送r0
ldr r1,=Label+1 //r1中是Label+1地址
ldrb r2,[r1] //r2中是Label+1地址中的数据
bl printf
ldr r0,=data_format1 //输出格式送r0
ldr r1,=Label+2 //r1中是Label+2地址
ldrb r2,[r1] //r2中是Label+2地址中的数据
bl printf
ldr r0,=data_format1 //输出格式送r0
ldr r1,=Label+3 //r1中是Label+3地址
ldrb r2,[r1] //r2中是Label+3地址中的数据
bl printf
//(2.3.1)清除循环次数变量
ldr r2,=mMainLoopCount //r2←mMainLoopCount的地址
mov r1,#0
str r1,[r2]
//(2.3.2)如灯状态标志mFlag为'L',灯的闪烁次数+1并显示,改变灯状态及标志
//判断灯的状态标志
ldr r2,=mFlag
ldr r6,[r2]
cmp r6,#'L'
bne main_light_off //mFlag不等于'L'转
//mFlag等于'L'情况
ldr r3,=mLightCount //灯的闪烁次数mLightCount+1
ldr r1,[r3]
add r1,#1
str r1,[r3]
ldr r0,=light_show3 //显示“灯的闪烁次数mLightCount=”
bl printf
ldr r0,=data_format //显示灯的闪烁次数值
ldr r2,=mLightCount
ldr r1,[r2]
bl printf
ldr r2,=mFlag //灯的状态标志改为'A'
mov r7,#'A'
str r7,[r2]
ldr r0,=LIGHT_BLUE //亮灯
ldr r1,=LIGHT_ON
bl gpio_set
ldr r0, =light_show1 //显示灯亮提示
bl printf
//mFlag等于'L'情况处理完毕,转
b main_exit
//(2.3.3)如灯状态标志mFlag为'A',改变灯状态及标志
main_light_off:
ldr r2,=mFlag //灯的状态标志改为'L'
mov r7,#'L'
str r7,[r2]
ldr r0,=LIGHT_BLUE //暗灯
ldr r1,=LIGHT_OFF
bl gpio_set
ldr r0, =light_show2 //显示灯暗提示
bl printf
main_exit:
b main_loop //继续循环
//(2)======主循环部分(结尾)=====================================
.end //整个程序结束标志(结尾)
运行结果:

蓝灯持续闪烁

作业#
一、翻译汇编成C语言#
将参考代码中 94~101行语句用C语言描述。
- 汇编语句
main_loop:
ldr r2,=mMainLoopCount
ldr r1, [r2]
add r1,#1
str r1,[r2]
ldr r2,=MainLoopNUM
cmp r1,r2
blO main_loop
- C 语言描述
const uint32_t MainLoopNUM = 6122338;
uint32_t mMainLoopCount = 0;
do
{
mMainLoopCount += 1;
}while(mMainLoopCount < MainLoopNUM);
二、修改参考代码#
- 在第一行显示 “广州大学” 字样。
增加代码:
.section .data
...
ToolTips:
.ascii "广州大学 32106100066\n\0"
data_format2:
.ascii "%s\n\0"
...
main:
...
tip: //打印提示信息:广州大学
ldr r0,=data_format2
ldr r1,=ToolTips
bl printf
bl .
...
main_loop:
运行结果

- 编写一个 1+2+...+10 的程序,将求和结果存入名为 “sumresult” 的内存单元中,并将求和结果用 printf 显示出来
增加代码:
.section .data
...
data_format3:
.ascii "%s%d\n\0"
sum_show:
.ascii "1+2+3+4+5+6+7+8+9+10=\0"
...
sumresult:
.word 0
...
main:
...
sum: //求和计算程序
mov r0,#0
mov r1,#1
mov r2,#10
sum_loop: //for循环计算
cmp r1,r2
bhi sum_outcome
add r0,r1
add r1,#1
b sum_loop
sum_outcome: //保存并打印结果
ldr r1,=sumresult
str r0,[r1] //存储到sumresult
ldr r0,=data_format3
ldr r1,=sum_show
ldr r3,=sumresult
ldr r2,[r3]
bl printf
bl .
...
main_loop:
运行结果:

- 编写示例程序:datax、datay、dataz 三个数中,找出最大值并显示。
增加代码:
.section .data
...
data_format4:
.ascii "0x%x、0x%x、0x%x\0"
data_format5:
.ascii "%s0x%x\n\0"
max_show:
.ascii " 进行有符号比较,其中最大值为:\0"
...
datax:
.word 0x87654321
datay:
.word 0x12345678
dataz:
.word 0x06100066
datamax:
.word 0
...
main:
...
compare1: //对三个数进行有符号比较得出最大值datamax
ldr r2,=datax
ldr r0,[r2]
ldr r2,=datay
ldr r1,[r2]
cmp r0,r1
blt save2
save1:
ldr r2,=datamax
str r0,[r2]
b compare2
save2:
ldr r2,=datamax
str r1,[r2]
b compare2
compare2:
ldr r2,=datamax
ldr r0,[r2]
ldr r2,=dataz
ldr r1,[r2]
cmp r0,r1
blt save4
save3:
ldr r2,=datamax
str r0,[r2]
b max_outcome
save4:
ldr r2,=datamax
str r1,[r2]
b max_outcome
max_outcome:
ldr r0,=data_format4
ldr r6,=datax
ldr r1,[r6]
ldr r6,=datay
ldr r2,[r6]
ldr r6,=dataz
ldr r3,[r6]
bl printf
ldr r0,=data_format5
ldr r1,=max_show
ldr r3,=datamax
ldr r2,[r3]
bl printf
bl .
...
main_loop:
运行结果:

【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步