目錄
- 原始參考程式碼(main.s)
- 作業
- 一、翻譯彙編成C語言
- 二、修改參考程式碼
原始參考程式碼(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:
執行結果: