㈠ 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在C里嵌入匯編語言
__asm 2個 _
然後 mov ax,0 要有豆號
比如
void CMainWindow::Fuck()
{
__asm{
push ebp
mov ebp,esp
sub esp,08h
mov byte ptr[ebp-08h],63h
mov byte ptr[ebp-07h],61h
mov byte ptr[ebp-06h],6ch
mov byte ptr[ebp-05],63h
mov byte ptr[ebp-04h],0h
mov byte ptr[ebp-03h],0h
mov byte ptr[ebp-02h],0h
mov byte ptr[ebp-01h],0h
lea eax,[ebp-08h]
push 0
push eax
mov eax,WinExec
call eax
add esp,08h
mov esp,ebp
pop ebp
}
}
㈢ 為什麼要C和匯編混合編程
依我的看法,上面兩位說的都不對:
一樓:匯編語言是低級語言直接往硬體的寄存器里寫入東西:
其實C語言和匯編語言都一樣,都會編譯成二進制文件機器語言燒錄到單片機中,所以沒有一樓所說的區別
二樓:在C中也不會有數據損失的,如果你定義好數據類型的話。
單片機中是將C編譯成匯編,然後根據匯編編譯成機器語言---可執行文件;
其實單片機中經常在C中嵌入匯編,主要是因為時間的關系,因為一條匯編語言執行的時間都是可以知道的,而C指令執行的時間是不可知的,因為C編譯器不一樣,編譯後的匯編也是不一樣的,如果用匯編就不會有這種情況。所以在一些精確延時的場合,要嵌入匯編
另外,C的可移植性較強,不同的單片機里,功能要求相同的可以直接拿去用
總之,匯編是程序員可以自己翻譯成機器語言的,所以單片機的運行是可以完全掌握的
㈣ arm的c語言和匯編混合編程,字元串的互換,求改正
你的函數體呢???
㈤ ARM 匯編與C程序的混合編程(怎樣實現4個以上的參數的傳遞)!
ADD proc
arg_C equ 0xC
arg_8 equ 8
arg_4 equ 4
arg_0 equ 0
MOV R12, SP
STMFD SP!, {R0-R3} ;四個參數氏蔽
STMFD SP!, {R4-R10,R12,LR}
SUB SP, SP, #0x10
LDR R0, [SP,#0x34+arg_0]
LDR R1, [SP,#0x34+arg_4]
LDR R2, [SP,#0x34+arg_8]
ADD R0, R0, R1
ADD R0, R0, R2
ADD SP, SP, #0x10
LDMFD SP, {R4-R10,SP,PC}
ENDP
如果參基核閉數傳遞大於 4 個,那麼你在 BL 的地方應使用:
....
STR R0, [SP,#0x8] ;第七個搏裂
STR R0, [SP,#0x4] ;第六個
STR R0, [SP,#0x0] ;第五個
============================================
我理解你的意思了
LDR r0,=0x1
LDR r1,=0x2
LDR r2,=0x3
BL add
改為:
LDR r0,=0x1
STR R0, [SP,#0x0]
LDR r1,=0x2
STR R1, [SP,#0x4]
LDR r2,=0x3
STR R2, [SP,#0x8]
BL ADD
你是這個意思吧?
------------
int a = R0
int b = R1
int c = R2
㈥ 嵌入式ARM 混合編程,匯編調用C語言,在線等
段定義前加 PRESERVE8 偽指令試一下。
前兩天剛好看到 ARM UCOS 匯編代碼中用到PRESERVE8這個關鍵字(加在段定義之前),以前沒見過的,於是網路。
1.匯編代碼沒有保持8位元組棧對齊而調用C或C++代碼。
2.ADS下的代碼用RVDS2.2編譯時,即使已經8位元組棧對齊,連接器也將之當作非8位元組棧對齊。
所以要用偽指令指明一下。
E文不好,故而附原文以供參詳:
where assembler code (that does not preserve 8-byte stack alignment) calls compiled C/C++ code (that requires 8-byte stack alignment), and
when attempting to link legacy SDT/ADS objects with RVCT 2.x objects. Legacy SDT/ADS objects that do not have these attributes are treated as '~PRES8', even if they do actually happen to preserve 8-byte alignment.
㈦ c語言和匯編語言混合之和如何編譯連接
如果你是想在一個文件里混寫c語言和arm匯編,這個跟編譯器有關系,如果你用gcc,可以用__asm__語法,請自行搜索__asm__相關資料
另一種方法,就是arm匯編文件和c語言文件分開來寫,在c語言中聲明函數符號即可。然後分別編譯後再用鏈接器鏈到一起
請參考
㈧ 怎麼實現c語言與匯編語言的混合編程
這個問題有很多做法。如果你的匯編語句比較簡單可以採用樓上的做法。
如果的你的匯編比較大,可以寫成另外一個匯編文件*.asm。然後根據你的編譯器給你的指令,把你的匯編函數抽象出C語言聲明。做成*.h文件,供其他人調用。這是現在比較流行的底層API開發模式。
如 我把需要用匯編語句寫的功能寫一個匯衫襲編文件 asm_main.asm,我在該文件的前面 加一句 XDEF asm_main(這是我的編譯器的規定,用XDEF),然後在asm_main.h里聲明(就是典型的C聲明 如 U16 asm_main())。這樣你在你的C程序中如果用到匯編功能,只要#include "asm_main.h" 就可以調用用匯編寫的函數了。對於大規模的軟體開發,這是虧橡個很重要的方法。它提供了二次介面供上層調用。你可以把所有硬體驅動或底層API都寫成這樣子。C語言開發者就不需要了解底層硬體細節了。而且底層匯編的改動也不會影響C。這樣你開發的C程序可移植性就高了。當然,你還需要些編譯原理銷塌旁的知識。如,在匯編里,asm_main函數只是個標號,寫成asm_main: 對吧,但是如果你需要些入口參數怎麼辦?比如你要抽象出U16 asm_main(char ,char *),這個時候你要考慮參數是怎樣入棧的,一般是從右到左依次壓棧的,等等還有些問題。
現在的大學本科教育只教一些單片機開發的小技能,沒有一個系統的概念。我很願意把我工作中得來的經驗與大家分享。