作者:毛蘢瑋 / Saint
GitHub :github.com/saint-000
test1.1ARM資料處理指令定址方式實驗和ARM記憶體訪問指令定址方式實驗中程式碼如下:
通過除錯可以發現知道程式碼中的資料傳送指令MOV;算術運算指令-加法指令ADD和減法指令SUB;以及比較指令CMP等資料處理指令在暫存器的數值和地址的變化,初步瞭解ARM的定址方式以及資料傳送方式。
test1.2程式設計實現1+2+…+N 程式碼書寫:
;功能:計算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之和,所以成功實現該功能。
test1.3理解C和彙編,並用彙編程式實現字串拷貝,並在C程式中呼叫該彙編程式。
在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偽操作告訴編譯器當前的符號不是在本原始檔中定義的,而是在其他原始檔中定義的,在本原始檔中可能引用該符號,而且不論本原始檔是否實際引用該符號,該符號都將被加入到本原始檔的符號表中。
複製程式碼