體會KEIL5數據處理和傳輸過程

做者:毛蘢瑋 / Saintgit

掘金:juejin.im/user/5aa1f8…github

微博:weibo.com/5458277467/…算法

GitHub :github.com/saint-000編程

test1.1ARM數據處理指令尋址方式實驗和ARM內存訪問指令尋址方式實驗中代碼以下:bash

經過調試能夠發現知道代碼中的數據傳送指令MOV;算術運算指令-加法指令ADD和減法指令SUB;以及比較指令CMP等數據處理指令在寄存器的數值和地址的變化,初步瞭解ARM的尋址方式以及數據傳送方式。函數

test1.2編程實現1+2+…+N 代碼書寫:ui

;功能:計算1+2+3+4+...+N
;說明;N>=0,當N=0時結果爲0,當N=1時結果爲1
N EQU 100   ;定義N的值100
	AREA Examples,CODE,READONLY   ;聲明代碼斷Examples3
	ENTRY   ;標識程序入口 
	
	CODE32
ARM_CODE
LDR SP,=0X30003F00    ;設置堆棧指針
	ADR R0,THUMB_CODE+1    
	BX R0        ;跳轉並切換處理器狀態
	LTORG        ;聲明文字池	
CODE16
THUMB_CODE
LDR R0,=N    ;設置子程序SUM_N的入口參數 
	BL SUM_N     ;調用子程序SUM_N
	B THUMB_CODE 
	
;SUM_N
;功能:計算1+2+3+......+N
;入口參數:R0 N的值
;出口參數:R0 運行結果 
;佔用資源:R0
;說明:當N=0時結果爲0,當N=1時結果爲1
;若運算溢出,結果爲0
SUM_N
	PUSH {R1-R7,LR}  ;寄存器入棧保護
	MOVS R2,R0       ;將n的值複製到R2,並影響相應條件標誌
	BEQ SUM_END      ;若N=0,則返回,成當即返回
	CMP R2,#1 ;比較R2是否爲1
	BEQ SUM_END      ;若N=1,則返回,成當即返回
	MOV R1,#1 ;初始化計數器R1=1 MOV R0,#0 ;初始化計數器R0=0 
SUN_L1
	ADD R0,R1		 ;R0=R1+R0
	BVS SUM_END		 ;溢出	
	CMP R1,R2		 ;比較R1和n是否相等
	BVS SUM_END		 ;相等,跳出循環,即加到n結束
	ADD R1,#1 ;R1=R1+1;
	B SUN_L1		 ;跳轉循環
SUM_ERR
	MOV R0,#0 ;R0=0
SUM_END 
	MOV R8,R0		 ;將結果保存在R8中
	POP {R1-R7,PC}   ;寄存器出棧,返回
        
	END
複製代碼

結果: 最終寄存器R8的讀數爲爲0X000013BA,數值爲十進制的5050,正好是從1加至100之和,因此成功實現該功能。spa

test1.3理解C和彙編,並用彙編程序實現字符串拷貝,並在C程序中調用該彙編程序。3d

在C程序中調用該彙編程序:指針

;文件名:main.c
;功能:完成字符串的拷貝
#include <stdio.h>
extern void strcopy(char *d ,char *s);
int main(void)
{
	char *srcstr = "aaaa";
	char dststr[] = "bbbb";
	//printf("Before copying:\n");				//仿真調試時禁用printf語句
	//printf(" %s %s\n",srcstr,dststr);
	strcopy(dststr,srcstr);
	//printf("After copying: \n");
	//printf(" %s\n %s\n",srcstr,dststr);
	return (0);

}
複製代碼

在彙編程序中:

;文件名:TEST.S 
;功能:從C語言中調用匯編語言
AREA	Example1,CODE,READONLY	;聲明代碼段Example1 
CODE32				   ;聲明32位ARM指令
IMPORT __main
EXPORT strcopy
strcopy	
	LDRB  R2,[R1],#1 ;拷貝源字符串的一個字節
	STRB  R2,[R0],#1 ;將拷貝的字節複製到目標空間,
	CMP   R2,#0 ;比較R2=0
	BNE   strcopy	
	MOV   PC,LR
	END			     	  

複製代碼

結果: 將原來的aaaa bbbb的值變成了aaaa aaaa,因此成功實現字符串複製。

test1.4在彙編中調用C函數

;文件名:main.c
;功能:完成求和
int g(int a, int b ,int c,int d)
{
	return a+b+c+d;
}

;文件名:TESTFILE.S 
;功能:從彙編語言中調用C語言
		IMPORT g
AREA	Example1,CODE,READONLY	  	
		CODE32				  	
		ENTRY
START	
		MOV		R0,#1 
		MOV		R1,#2
		MOV		R2,#3
		MOV		R3,#10
		BL		g
		MOV		R8,R0	
		B		START

		END

複製代碼

結果: 最終寄存器R8讀數爲0X000010,正好爲1+2+3+10=16,因此正確實現該功能。

test1.5用ARM彙編實現冒泡算法。

AREA Sort,CODE,READONLY
	ENTRY
start
	MOV r4,#0
	LDR r6,=src
	ADD r6,r6,#len
outer
	LDR r1,=src
inner
  LDR r2,[r1]
  LDR r3,[r1,#4]
  CMP r2,r3
  STRGT r3,[r1]
  STRGT r2,[r1,#4]
  ADD r1,r1,#4
  CMP r1,r6
  BLT inner
  
  ADD r4,r4,#4
  CMP r4,#len
  SUBLE r6,r6,#2
  BLE outer
src DCD 2,4,10,8,14,1,20
    AREA Array,DATA,READWRITE
len EQU 7*4
	END
複製代碼

結果: 從起始寄存器位置開始,每一個四個輸出一個數據,數據依次爲1,2,4,8,10,14,20,由此完成了冒泡排序法。    

心得: (1)在寫冒泡排序過程當中發現,若是使用雜項僞命令AREA定義數據段時, AREA Sort,CODE,READONLY這段代碼要縮進,以及跟下面結束時的相同代碼對齊,不然會出現編譯錯誤。

(2)咱們在使用memory map的時候,須要查看同一個寄存器的首地址和尾地址的數據變化,咱們須要將程序剛開始的寄存器首地址和結束時的尾地址填入memory map中,注意格式以下:

思考:

1.ADD替換成ADDS,SUB替換成SUBS有什麼影響?

運算結果不影響CPSR中相應標誌位的值,跳轉指令由於上一步的CPSR的值沒有改  
變而沒法正確執行。S用於決定指令的操做是否影響CPSR中的條件標誌位。
複製代碼

2.MOV替換成MOVNE有什麼影響?

只有在上一步計算結果爲不相等時才執行。MOVNE先判斷條件NE (不相等)則轉移,能夠看做是兩條指令NE=NOT EQUAL不相等。
複製代碼

3.STMIA換成STMIB,STMIA換成STMDA有什麼區別?

STMIA換成STMIB是將每次寫入前地址+4改成地址-4,STMIA換成STMDA是將每次寫入前地址+4改成+1 ,其中STMIB(地址先增然後完成操做)、STMFA(滿遞增堆棧);
STMIA(完成操做然後地址遞增)、STMEA(空遞增堆棧);STMDB(地址先減然後完成操做)、STMFD(滿遞減堆棧);STMDA(完成操做然後地址遞減)、STMED(空遞減堆棧)。
複製代碼

4.思考用ARM彙編實現1+3+5+…+(2n+1)或者2+4+6+…+2n。

實現1+3+5+„.+(2n+1):   
將 add r1,r1,#1 改成 add r1,r1,lsl  #1       sub r1,r1,#1   
實現2+4+6+…..+2n:   
將 add r1,r1,#1 改成 add r1,r1,lsl  #1  
複製代碼

5.實驗3中若是去除彙編代碼中的「EXPORT strcopy」會有什麼現象,爲何?

C語言沒法調用用strcopy函數。由於EXPORT僞指令用於在程序中聲明一個全局的標  
號,該標號可在其餘的文件中引用。
複製代碼

6.實驗4中若是去除彙編代碼中的「IMPORT …..」會有什麼現象,爲何?

把「IMPORT ….註釋後發現,編譯調試時程序單步運行直接從彙編程序開始,說明沒法調用C語言的main函數。IMPORT僞操做告訴編譯器當前的符號不是在本源文件中定義的,而是在其餘源文件中定義的,在本源文件中可能引用該符號,並且不論本源文件是否實際引用該符號,該符號都將被加入到本源文件的符號表中。
複製代碼
相關文章
相關標籤/搜索