做者:毛蘢瑋 / Saintgit
掘金:juejin.im/user/5aa1f8…github
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.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僞操做告訴編譯器當前的符號不是在本源文件中定義的,而是在其餘源文件中定義的,在本源文件中可能引用該符號,並且不論本源文件是否實際引用該符號,該符號都將被加入到本源文件的符號表中。
複製代碼