本周作业
(1)打开“04-Software/ch02/CH02-1-20220118”工程目录,编译下载运行,理解并学习main.s汇编源文件。
(2)写出main.s中94~101行语句的c语言描述
(3)修改main.s源文件,增加以下内容:
·在第一行显示“广州大学”字样。
·编写一个1+2+...+10的程序,将求和结果存入名为“sumresult”的内存单元中,并将求和结果用printf显示出来。
注:建议在源程序中“main_loop:”语句之前的地方添加,结束时用“bl .”停住。printf的格式详见05_UserBoard/printf.h文件。
任务一:打开“04-Software/ch02/CH02-1-20220118”工程目录,编译下载运行,理解并学习main.s汇编源文件。
(1)打开CH02-1-20220118,理解源码
1. 数据段与代码段的定义:定义需要输出的字符串、格式控制符、变量等数据存储在RAM中,定义代码存储在Flash中。
2. 主函数初始化部分:
开始:关总中断,给局部变量和全局变量赋初值,初始化蓝灯和串口UART_User1,开总中断。
结尾:显示hello_information定义的字符串。
3. 主循环部分:
主循环次数控制,当达到设定值后进行灯的亮暗处理。
测试代码部分:将Label地址中的数据逐个输出,理解机器码存储。
灯的状态标志mFlag为'L'时,灯的闪烁次数+1并显示,改变灯状态及标志。
灯的状态标志mFlag为'A'时,改变灯状态及标志。
4. 主函数结尾标志:程序结束。
(2)编译运行一下程序。具体操作是:单击“编译”,单击“编译工程”,等待“编译成功”;单击“下载”,单击“串口更新”,打开新窗口;单击“连接GEC”,单击“选择文件”,选择“Debug”中的“.hex”后缀文件,单击“一键自动更新”。
任务二:写出main.s中94~101行语句的C语言描述。
原来的汇编语言:
main_loop: //主循环标签(开头)
//(2.1)主循环次数变量mMainLoopCount+1
ldr r2,=mMainLoopCount //r2←mMainLoopCount的地址
ldr r1, [r2]
add r1,#1
str r1,[r2]
//(2.2)未达到主循环次数设定值(include.inc中,值为6122338),继续循环
ldr r2,=MainLoopNUM
cmp r1,r2
blO main_loop //未达到,继续循环
//(2.3)达到主循环次数设定值(作用为灯闪烁间隔时间),执行下列语句,进行灯的亮暗处理
改写后的c语言代码描述:
void main_loop() {
// 主循环次数变量mMainLoopCount+1
int* r2 = &mMainLoopCount;
int r1 = *r2;
r1 += 1;
*r2 = r1;
// 未达到主循环次数设定值,继续循环
int* r2 = &MainLoopNUM;
if (r1 < *r2) {
// 继续循环
main_loop();
}
// 达到主循环次数设定值,执行下列语句,进行灯的亮暗处理
// 灯的状态为亮,闪烁次数+1并显示
if (mFlag == 'L') {
blink_times++; // 闪烁次数+1
LED_on(); // 灯亮
printf("LED is blinking. Blink times: %d\n", blink_times);
mFlag = 'A'; // 改变灯的状态为暗
}
// 灯的状态为暗,改变灯的状态
else if (mFlag == 'A') {
LED_off(); // 灯暗
mFlag = 'L'; // 改变灯的状态为亮
}
}
上面的C语言描述模拟了汇编语言中的主循环部分,包括了主循环次数的变化、未达到次数设定值时的继续循环以及达到次数设定值时灯的亮暗处理。函数内部递归调用模拟了汇编语言中的跳转操作。
任务三:修改main.s源文件,增加以下内容:
一、在第一行显示“广州大学”字样
1、学习如何使用printf,tips:printf的格式详见05_UserBoard/printf.h文件。
2、编写代码
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"
gzhu_information:
.ascii "\n<------------------------------------------------------>\n"
.ascii "\n 广州大学 \n"
.ascii "\n lishukai \n"
.ascii "\n<------------------------------------------------------>\n\0"
...
//1.显示gzhu_information定义的字符串
ldr r0,=gzhu_information //待显示字符串首地址
bl printf //调用printf显示字符串
//(1)======启动部分(结尾)=======================================
//(2)======主循环部分(开头)=====================================
main_loop
...
编译成功并运行:
二、编写一个1+2+...+10的程序,将求和结果存入名为"sumresult"的内存单元中,并将求和结果用printf显示出来
代码如下:
.section .data
……
sumresult:
.word 0
sumresult_show:
.ascii "1-10累加求和sumresult=%d\0\n"
……
mov r1,#0
mov r2,#0
sum_loop:
add r1,#1
add r2,r1
cmp r1,#10
blO sum_loop //未达到10,继续循环
//end sum_loop
ldr r1,=sumresult //结果存入内存
str r2,[r1]
ldr r0,=sumresult_show //printf结果
ldr r2,=sumresult
ldr r1,[r2]
bl printf
bl .//打桩(无限循环)
结果如下:
作业完成。