導航:首頁 > 編程語言 > arm匯編程序100例

arm匯編程序100例

發布時間:2023-06-20 07:48:48

Ⅰ arm編程,c語言中嵌入匯編實現1+2+3+...+100

C語言中static關鍵字的常見用法及舉例

在嵌入式系統開發中,目前使用的主要編程語言是C和匯編,

C++已經有相應的編譯器,但是現在使用還是比較少的。在稍大

規模的嵌入式軟體中,例如含有OS,大部分的代碼都是用C編

寫的,主要是因為C語言的結構比較好,便於人的理解,而且有

大量的支持庫。盡管如此,很多地方還是要用到匯編語言,例如

開機時硬體系統的初始化,包括CPU狀態的設定,中斷的使能,

主頻的設定,以及RAM的控制參數及初始化,一些中斷處理方

面也可能涉及匯編。另外一個使用匯編的地方就是一些對性能非

常敏感的代碼塊,這是不能依靠C編譯器的生成代碼,而要手工

編寫匯編,達到優化的目的。而且,匯編語言是和CPU的指令集

緊密相連的,作為涉及底層的嵌入式系統開發,熟練對應匯編語

言的使用也是必須的。

單純的C或者匯編編程請參考相關的書籍或者手冊,這里主要討

論C和匯編的混合編程,包括相互之間的函數調用。下面分四種

情況來進行討論,暫不涉及C++。

1. 在C語言中內嵌匯編

在C中內嵌的匯編指令包含大部分的ARM和Thumb指令,不過其

使用與匯編文件中的指令有些不同,存在一些限制,主要有下面

幾個方面:

a. 不能直接向PC寄存器賦值,程序跳轉要使用B或者BL指令

b. 在使用物理寄存器時,不要使用過於復雜的C表達式,避免物理寄存器沖突

c.
R12和R13可能被編譯器用來存放中間編譯結果,計算表達式值時可能將R0到R3、R12及R14用於子程序調用,因此要避免直接使用這些物理寄存器

d. 一般不要直接指定物理寄存器,而讓編譯器進行分配

內嵌匯編使用的標記是 __asm或者asm關鍵字,用法如下:

__asm

{

instruction [; instruction]



[instruction]

}

asm(「instruction [; instruction]」);

下面通過一個例子來說明如何在C中內嵌匯編語言,

#include

void my_strcpy(const char *src, char *dest)

{

char ch;

__asm

{

loop:

ldrb ch, [src], #1

strb ch, [dest], #1

cmp ch, #0

bne loop

}

}

int main()

{

char *a = "forget it and move on!";

char b[64];

my_strcpy(a, b);

printf("original: %s", a);

printf("ed: %s", b);

return 0;

}

在這里C和匯編之間的值傳遞是用C的指針來實現的,因為指針

對應的是地址,所以匯編中也可以訪問。

2. 在匯編中使用C定義的全局變數

內嵌匯編不用單獨編輯匯編語言文件,比較簡潔,但是有諸多限

制,當匯編的代碼較多時一般放在單獨的匯編文件中。這時就需

要在匯編和C之間進行一些數據的傳遞,最簡便的辦法就是使用

全局變數。

/* cfile.c

* 定義全局變數,並作為主調程序

*/

#include

int gVar_1 = 12;

extern asmDouble(void);

int main()

{

printf("original value of gVar_1 is: %d", gVar_1);

asmDouble();

printf(" modified value of gVar_1 is: %d", gVar_1);

return 0;

}

對應的匯編語言文件

;called by main(in C),to double an integer, a global var defined in C

is used.

AREA asmfile, CODE, READONLY

EXPORT asmDouble

IMPORT gVar_1

asmDouble

ldr r0, =gVar_1

ldr r1, [r0]

mov r2, #2

mul r3, r1, r2

str r3, [r0]

mov pc, lr

END

3. 在C中調用匯編的函數

在C中調用匯編文件中的函數,要做的主要工作有兩個,一是在

C中聲明函數原型,並加extern關鍵字;二是在匯編中用

EXPORT導出函數名,並用該函數名作為匯編代碼段的標識,最

後用mov pc, lr返回。然後,就可以在C中使用該函數了。從

C的角度,並不知道該函數的實現是用C還是匯編。更深的原因

是因為C的函數名起到表明函數代碼起始地址的左右,這個和匯

編的label是一致的。

/* cfile.c

* in C,call an asm function, asm_strcpy

* Sep 9, 2004

*/

#include

extern void asm_strcpy(const char *src, char *dest);

int main()

{

const char *s = "seasons in the sun";

char d[32];

asm_strcpy(s, d);

printf("source: %s", s);

printf(" destination: %s",d);

return 0;

}

;asm function implementation

AREA asmfile, CODE, READONLY

EXPORT asm_strcpy

asm_strcpy

loop

ldrb r4, [r0], #1 ;address increment after read

cmp r4, #0

beq over

strb r4, [r1], #1

b loop

over

mov pc, lr

END

在這里,C和匯編之間的參數傳遞是通過ATPCS(ARM

Thumb Procere Call Standard)的規定來進行的。簡單的說就

是如果函數有不多於四個參數,對應的用R0-R3來進行傳遞,多

於4個時藉助棧,函數的返回值通過R0來返回。

4. 在匯編中調用C的函數

在匯編中調用C的函數,需要在匯編中IMPORT 對應的C函數名

,然後將C的代碼放在一個獨立的C文件中進行編譯,剩下的工

作由連接器來處理。

;the details of parameters transfer comes from ATPCS

;if there are more than 4 args, stack will be used

EXPORT asmfile

AREA asmfile, CODE, READONLY

IMPORT cFun

ENTRY

mov r0, #11

mov r1, #22

mov r2, #33

BL cFun

END

/*C file, called by asmfile */

int cFun(int a, int b, int c)

{

return a + b + c;

}

在匯編中調用C的函數,參數的傳遞也是通過ATPCS來實現

的。需要指出的是當函數的參數個數大於4時,要藉助stack,具

體見ATPCS規范

Ⅱ arm常用幾個匯編語言的程序

一。從一數到十
COUNT EQU 0x30003100 ;定義變數COUNT的基地址 AREA Example1,CODE,READONLY;聲明代碼段Example1為只讀 ENTRY ;標識程序入口

CODE32 ;聲明32位ARM指令 START LDR R1,=COUNT ;將0X30003100賦給R1 MOV R0,#0 ;執行R0=0
STR R0,[R1] ;存儲R0寄存器的數據到R1指向的存儲單元 LOOP LDR R1,=COUNT ;將0X30003100賦給R1
LDR R0,[R1] ;將R1中的數值作為地址,取出此地址中的數據保存到R0中 ADD R0,R0,#1 ;執行R0=R0+1
CMP R0,#10 ;將R0與10進行比較
MOVHS R0,#0 ;若R0大於等於10,則R0=0
STR R0,[R1] ;存儲R0寄存器的數據到R1指向的地址單元 B LOOP ;跳轉到LOOP
END ;匯編文件結束
二,9的8次冪
X EQU 9 ;初始化X為9 n EQU 8 ;初始化N為8
AREA Example3,CODE,READONLY ;生明代碼段Example3為只讀 ENTRY ;標識程序入口路
CODE32 ;聲明32位ARM指令
START LDR SP,=0x30003F00 ;把0x30003F00 賦給SP(R13) LDR R0,=X ;把9賦給R0 LDR R1,=n ;把8賦給R1
BL POW ;跳轉到POW,並把下一條指令地址存入到R14中 HALT B HALT ;等待跳轉
POW STMFD SP!,{R1-R12,LR} ;將R1-R12入棧,滿遞減堆棧 MOVS R2,R1 ;將R1賦給R2,並影響標志位 MOVEQ R0,#1 ;若Z=1,則R0=1
BEQ POW_END ;若Z=1,跳轉到POW_END MOV R1,R0 ;將R0中值賦給R1 SUB R2,R2,#1 ;將R2-1的只賦給R2 POW_L1 BL DO_MUL ;跳轉到DO-MUL,並把下一條指令地址存入R14中 SUBS R2,R2,#1 ;將R2-1的值賦給R2,並影響標志位 BNE POW_L1 ;若Z=0,跳轉到POW_L1
POW_END LDMFD SP!,{R1-R12,PC} ;數據出棧,存入到R1-R12,PC中 DO_MUL MUL R0,R1,R0 ;把R1*R0的值賦給R0 MOV PC,LR ;LR中的值賦給PC END ;匯編結束
三:從一一直加到一百
程序清單(一) C 語言實驗參考程序
#define uint8 unsigned char ;定義一個無符號字元常量uint8 #define uint32 unsigned int ;定義一個無符號整型常量unint32
#define N 100 ;定義一個常量N=100(宏定義,100用N代替) uint32 sum; ;定義sum為無符號整型常量(聲明一個unsigned int型的變數sum) void Main(void) ;主函數
{uint32 i; ;定義無符號整型常量i(聲明一個unsigned int型的變數i) sum=0; ;sum初始值為0
for(i=0;i<=N;i++) ;i在N內自增加1(i從0開始,i<=N時循環成立) {sum+=i;} ;把sum+i賦給sum while(1); ;為真循環 }
程序清單(二) 簡單的啟動代碼
IMPORT |Image$$RO$$Limit | ;R0輸出段存儲區域界線 IMPORT |Image$$RW$$Base | ;RW輸出段運行時起始地址 IMPORT |Image$$ZI$$Base | ;ZI輸出段運行時起始地址 IMPORT |Image$$ZI$$Limit | ;ZI輸出段存儲區域界線 IMPORT Main ;主函數
AREA Start,CODE,READONLY ;聲明代碼段start,為只讀 ENTRY ;程序入口
CODE32 ;聲明32位ARM指令 Reset LDR SP,=0x40003f00 ;將0x40003f00賦給SP
LDR R0,=|Image$$RO$$Limit| ;將R0輸出段存儲區域界線賦給R0 LDR R1,=|Image$$RW$$Base | ;將RW輸出段運行時起始地址賦給R1 LDR R3,=|Image$$ZI$$Base | ;將ZI輸出段運行時起始地址賦給R3 CMP R0,R1 ;比較R0和R1,相等Z=1,反之Z=0 BEQ LOOP1 ;若Z=1,則跳到LOOP1
LOOP0 CMP R1,R3 ;比較R1和R3,若R1<r3,c=0
LDRCC R2,[R0],#4 ;若C=0,讀取R0地址單元內容並且存入R2,且R0=R0+4 STRCC R2,[R1],#4 ;若C=0,讀取R2中的數據存入R1,且R1=R1+4 BCC LOOP0 ;若C=0,跳轉到LOOP0
LOOP1 LDR R1,=|Image$$ZI$$Limit| ;將ZI輸出段存儲區域賦給R1 MOV R2,#0 ;把0賦給R2
LOOP2 CMP R3,R1 ;比較R1和R3,若R1<r3,c=0 strcc="" r2,[r3],#4="" ;若c="0,將R2中數據保存到內存單元R3中,且R3=R3+4" bcc="" loop2="" b="" main="" ;跳轉到主程序="" end="" ;匯編結束=""
四、程序清單(一) C 語言調用匯編的參考程序
#define uint8 unsigned char ;定義一個無符號字元常量uint8 #define uint32 unsigned int ;定義一個無符號整型常量.uint32
extern uint32 Add(uint32 x,uint32 y); //聲明子程序Add為一個無符號整型常量,它為2個無符號整型常量x,y的和
uint32 sum; ;定義sum為無符號整型常量 void Main(void) ;無返回主程序
{sum=Add(555,168); ;sum等於555+168 while(1); ;為真循環 }
程序清單(二) 匯編加法函數程序

EXPORT Add ;聲明子程序Add方便調用 AREA Start,CODE,READONLY ;聲明代碼段start,為只讀 ENTRY ;程序入口
CODE32 ;聲明32位ARM指令
Add ADD R0,R0,R1 ;將R0+R1值賦給R0 MOV PC,LR ;將LR值賦給PC

閱讀全文

與arm匯編程序100例相關的資料

熱點內容
ping命令設置包大小和周期 瀏覽:669
Android怎麼找 瀏覽:359
cmd命令顯示中文 瀏覽:839
配置路由器默認路由的命令是 瀏覽:591
加密計算器是什麼 瀏覽:120
伺服器怎麼執行sql 瀏覽:974
小孩子命令 瀏覽:708
貸款申請系統源碼 瀏覽:268
windowsxp文件夾打開後怎麼返回 瀏覽:664
怎麼把pdf變成圖片 瀏覽:797
17年程序員事件 瀏覽:496
iishttp壓縮 瀏覽:31
公司文件加密後拷走能打開嗎 瀏覽:186
headfirstjava中文 瀏覽:894
騰訊雲伺服器怎麼放在電腦桌面 瀏覽:8
批量生成圖片的app哪個好 瀏覽:496
小米10電池校準命令 瀏覽:96
移動商城系統app如何開發 瀏覽:692
用安卓手機如何發高清短視頻 瀏覽:339
怎樣運行java程序運行 瀏覽:553