嵌入式作業2.1 彙編練習

一只心耳發表於2024-03-27

目錄
  • 原始參考程式碼(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     //整個程式結束標誌(結尾)

執行結果:

image-20240327200801792

藍燈持續閃爍

嵌入式作業2.1 彙編練習

作業

一、翻譯彙編成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);

二、修改參考程式碼

  1. 在第一行顯示 “廣州大學” 字樣。

增加程式碼:

.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:

執行結果

嵌入式作業2.1 彙編練習
  1. 編寫一個 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:

執行結果:

嵌入式作業2.1 彙編練習
  1. 編寫示例程式: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:

執行結果:

嵌入式作業2.1 彙編練習

相關文章