esp32 c3藍牙開發樂鑫科技華南代理商匯編程序示例,[例1] 計算 A=1+2+3+...+99+100。
分析:實現 1~100 的循環加法,并將結果保存到內存中。
在esp32 c3藍牙開發樂鑫科技華南代理商匯編語言程序中,聲明循環次數和變量 A 的存儲地址兩個常數。使用 0和t1 寄存器分別保存循環次數和變量 A 的臨時值。
在 gas 匯編語言中,用符號“NAME”代替特定值 VALUE 的聲明方式如下:
.equ NAME,VALUE//NAME = VALUE
示例5.3: 實現累加和的匯編程序。
/*1+2+...+99+100 */
1 .section .text,"ax" //聲明.text 段及其屬性
2 .global _start //聲明全局標簽_start,指定程序人口
3 .equ NUMBER,100 //設定循環次數
4 .equ MEMADD,0x400000 //設定存儲變量A的地址
5 _start:
6 li t0,NUMBER //計數寄存器t0循環初始值100
7 li t1,0 //累加加過寄存器t1清0
8 addloop: //行標簽
9 add t1 ,t1,t0 //t1=t1+10,累加計算
10 addi t0,t0,-1 //循環計數器-1
11 bltu x0,t0,addloop //if t0>0,循環計算
12 li t5,MEMADD //裝載存儲地址到 t5
13 sw t1,(t5) //保存數據到內存
14 nop //空操作
15 .end
在示例 5.3 中:
第 1、2 行,分別聲明段屬性和全局標簽;
第 3、4 行,常數聲明;
第 6、7 行,裝載立即數,用偽指令 li 裝任意 32 位數;
第 9、10 行,循環主體部分,第 9 行累加計算,第 10 行循環變量減 1,esp32 c3藍牙開發樂鑫科技華南代理商使用變量遞減方式進行循環;
第 13 行,保存數據,將累加結果從 t1 寄存器寫人內存 MEMADD 地址處。
0x11 0x120x13 0x14
[例2] 矩陣A= 0x21 0x22 0x23 0x24 ,計算A[3][0]= A[2][0]+A[1][0]。
0x31 0x32 0x33 0x34
esp32 c3藍牙開發樂鑫科技華南代理商分析: 從保存矩陣數據 內存中的兩個不同地址讀取數據,并將這兩個數據的和寫入矩陣數據內存中其他地址。
程序的主要關注點:
1 如何在程序中聲明數據段?
2 如何在內存中分配空間并初始化數據?
3 如何獲取所分配數據空間的地址?
示例 5.4:矩陣計算程序
/ Array */
1 . section . text,"ax' /聲明.text 段及其屬性
2 .global_start /聲明全局標簽 _start,指定程序入口
3 _start;
4 la a0, array //裝載矩陣數組起始地址
5 Iw al,4*4(a0) //讀取 A[1][0]
6 lw a4,8*4(a0) //讀取 A[2][0]
7 add al ,al ,a4 //相加
8 sw al,12 * 4(a0) //寫人A[3][0]
9 nop //空操作
10 . section .data_run,"w' //聲明可讀寫數據段
11 .global array //聲明全局標簽
12 array: //矩陣標簽
13 .word 0x11,0x12,0x13,0x14 //分配內存,并初始化數組
14 .word 0x21,0x22,0x23,0x2414 //分配內存,并初始化數組
15 .word 0x31,0x32,0x33,0x34 //分配內存,并初始化數組
16 .end //結束符
在示例 5.4中:
第 4行,使用偽指令 la 裝載數組在內存中的基地址 array;
第 5、6 行,從內存中讀取 4 字節數據;
第 8 行,把數據寫入內存中;
第 10 行,聲明運行時數據段及其屬性,可寫、可分配并初始化:第 11 行,聲明數據段地址標簽 array 為全局標簽;
第 13、14、15 行分配內存空間并設置初始數據。
[例3] 定義宏,實現任意兩個內存塊之間,任意長度的數據移動。esp32 c3藍牙開發樂鑫科技華南代理商使用所定義的宏,實現內存中長度 1K 數據的復制。
分析: 定義宏的名稱和輸入參數。輸入參數包括源地址、目標地址和數據長度將宏名稱定義為 MEMCPY,聲明 3 個參數分別是源地址存器“src”目標存器“dst”和數據長度寄存器“length”。
在 gas 匯編語言中,宏定義的命令格式如下:
.macro name arg.[,arg.] //聲明名稱是 name 的指令宏塊,arg 為形式參數。
在 gas 匯編語言中,“\”是宏塊中的輸入參數符。
程序的主要關注點:
1聲明宏的方式;
2宏定義中參數的表示形式;
3引用宏的方式。
示例5.5:宏定義聲明。
/* .macro definition */
1 .macro MEMCPY src,dst,length //宏名和參數定義
2 mv to,\length //復制長度寄存器
3 my t1,src //復制源地址寄存器
4 mv t2,\dst //復制目標地址寄存器
5 1: //局部標簽
6 Ib t3,(t1) //讀1字節
7 sb t3,(t2) //寫1字節
8 addi tl ,t1,1 //源地址+1
9 addi t2,t2,1 //目標地址 +1
10 addi t0,t0,- //長度計數器 -1
11 bltu x0,t0,1b //跳轉 1
12 .endm //宏結束
示例5.5中:
第 1、12 行,名字為 MEMCPY 宏的聲明和結束命令;
第 2~4 行,把參數寄存器的值復制到臨時寄存器;
第 6~10 行,循環主體,從源地址讀取(lb)一字節數據,寫入(sb)到目標地址??傃h次數是需要移動的數據長度。
第5行,局部標簽(local label)“1”,第 11行是跳轉到局部標簽的語句,“1b”中的“b”表示“back”往回跳(地址減小的方向)。如果跳向地址增加的方向(“forward”)則將“b”換成“f”。esp32 c3藍牙開發樂鑫科技華南代理商在同一個程序中可能多次引用宏,如果在宏中使用普通標簽,則可能出現程序中不同地址使用同一標簽的情形。因此,在宏塊中,使用局部標簽。
示例 5.6:主程序中引用宏。
/* .macro reference in program * /
1 .equ DSADD,0x20008000 //日標地址
2 .equ NUMBER,32 //數據長度
3 .section .text,"ax" //聲明.text 域和屬性
4 .global_start //聲明全局標簽 _start,指定程序入口
5 _start:
6 la a ,memdata //裝載源地址
7 li al,DSADD //裝載目標地址
8 li a3,NUMBER //裝載數據長度
9 MEMCPY a0,a1,a3 //引用宏
10 nop //空操作
11 .section .data_run,"wa", % progbits //數據區定義
12 .global memdata //數據標簽
13 memdata: //數據標簽
14 .word 0x11223344,0x22334455,0x33445566,0x44556677 //數據
15 .word 0x55667788,0x66778899,0x77889900,0x88990011 //數據
16 .word 0x99001122,0x88990011,0x99112233,0x88990011 //數據
17 .end
在示例5.6中。使用 MRMCPY將數據從初始數新區 memdatn 復制到目標地址0x20008000。
第 1、2 行,聲明目標地址和數據長度;
第 6~8 行,參數賦值;
第9行,引用宏 MEMCPY,引用方式與指令格式相似,宏名稱后跟隨實際參數。多引用時,esp32 c3藍牙開發樂鑫科技華南代理商實際參數的類型和數量必須與宏定義中形式參數的類型和數量一致。