c語言內嵌arm匯編
如果你是想在一個文件里混寫c語言和arm匯編,這個跟編譯器有關系,如果你用gcc,可以用__asm__語法,請自行搜索__asm__相關資料
另一種方法,就是arm匯編文件和c語言文件分開來寫,在c語言中聲明函數符號即可。然後分別編譯後再用鏈接器鏈到一起
Ⅱ c語言內嵌arm匯編,實現1+2+…+100
#include<stdio.h>
intmain(intargc,constchar*argv[])
{
intdata=0,result=0;
__asm__ __volatile__(
"movl$0,%[data] "
"movl$0,%0 "
"loop1:"
"inc%[data] "
"addl%[data],%0 "
"cmp$100,%[data] "
"jneloop1 "
:"=r"(result),[data]"=r"(data) /*Rotationresult.*/
:/*Rotatedvalue.*/
:/*Noclobbers*/
);
printf("result=%d,data=%d ",result,data);
return0;
}
gcc 的內聯匯編 , 執行效果:
$ gcc main.c -o main
$ ./main
result = 5050, data = 100
希望你滿意!
Ⅲ 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語言嵌套匯編中:"=&r"(a)什麼意思,=有時候就可以換成+實在不懂啊
p=&r跟*p=r區別&r是取變數r的地址,p=&r的意思是把變數r的地址賦給變數p,這種情況p一般是個指針。*p在等號左邊,表示對p指向的內存空間賦值
Ⅳ 求一匯編小程序!用ARM匯編語言完成一個C語言嵌入式匯編方式實現字元串(數組)拷貝的功能
#include< reg51.h>
#include< stdio.h>
#include< string.h>
#define INBUF_LEN 4 //數據長度
unsigned char inbuf1[INBUF_LEN];
unsigned char checksum,count3 , flag,temp,ch;
bit read_flag=0;
sbit cp=P1^1;
sbit DIR=P1^2;
int i;
unsigned int xdata *RAMDATA; /*定義RAM地址指針*/
unsigned char a[6] ={0x11,0x22,0x33,0x44,0x55,0x66} ;
void init_serialcomm(void)
{
SCON=0x50; //在11.0592MHz下,設置串列口波特率為9600,方式1,並允許接收
PCON=0x00;
ES=1;
TMOD=0x21; //定時器工作於方式2,自動裝載方式
TH0=(65536-1000)%256;
TL0=(65536-1000)/256;
TL1=0xfd;
TH1=0xfd;
ET0=1;
TR0=1;
TR1=1;
// TI=0;
EA=1;
// TI=1;
RAMDATA=0x1F45;
}
void serial () interrupt 4 using 3
{
if(RI)
{ RI=0;
ch=SBUF;
TI=1; //置SBUF空
switch(ch)
{
case 0x01 :printf("A"); TI=0;break;
case 0x02 :printf("B"); TI=0;break;
case 0x03 :printf("C"); TI=0;break;
case 0x04 :printf("D"); TI=0;break;
default :printf("fg"); TI=0;break;
}
}
}
//向串口發送一個字元
void timer0() interrupt 1 using 3{
// char i;
flag++;
TH0=0x00;
TL0=0x00;
if(flag==10)
{// cp=!cp;
// for(i=0;i<6;i++)
P2=0x25;
TI=1;
temp=*RAMDATA;
printf("%c",temp);
TI=0;
// RAMDATA--;
flag=0;
}
}
//主程序
main()
{
init_serialcomm(); //初始化串口
//向6264中送數據
{
*RAMDATA=0x33;
}
while(1)
{
*RAMDATA=0x33;;
}
}
Ⅵ 如何在C或C++代碼中嵌入ARM匯編代碼
C語言中嵌入匯編的方法是加入關鍵字「asm」來實現的,如: 例1: main() { asm mov ah,2; asm mov bh,0; asm mov dl, 20; asm mov dh,10; asm int 10h; } 例2: main() { asm{ mov ah,2; mov bh,0; mov dl, 20; mov dh,10; int 10h; } }
Ⅶ arm,c語言中嵌入ARM匯編,實現1+2+3+...+100
實在不會的話,先用C寫出來,然後再匯編調試界面看看匯編代碼,不是很難。
Ⅷ 如何在C語言中嵌入匯編
以下所說嵌入的匯編都是GUN 的C語言中嵌入ARM匯編。
1)2個參數的內嵌語句
這種形式的匯編用於簡單的語句,參數限制輸入和輸出語法格式如下:
asm(code : output operand list : inputoperand list : clobber list);
匯編和C語句這間的聯系是通過上面asm聲明中可選的output operand list和input operand list。Clobber list後面再講。
下面是將C語言的一個整型變數傳遞給匯編,邏輯左移一位後在傳遞給C語言的另外一個整型變數。
/* Rotating bits example */
asm("mov %[result], %[value], ror#1" : [result] "=r" (y) : [value] "r" (x));
每一個asm語句被冒號(:)分成了四個部分。
匯編指令放在第一部分中的「」中間。
"mov %[result], %[value], ror #1"
接下來是冒號後的可選擇的output operand list,每一個條目是由一對[](方括弧)和被他包括的符號名組成,它後面跟著限制性字元串,再後面是圓括弧和它括著的C變數。這個例子中只有一個條目。
[result] "=r" (y)
接著冒號後面是輸入操作符列表,它的語法和輸入操作列表一樣
[value] "r" (x)
為了增加代碼的可讀性,你可以使用換行,空格,還有C風格的注釋。
asm("mov %[result], %[value], ror#1"
: [result]"=r" (y) /* Rotation result. */
: [value]"r" (x) /* Rotated value. */
: /* No clobbers */
);
在代碼部分%後面跟著的是後面兩個部分方括弧中的符號,它指的是相同符號操作列表中的一個條目。
%[result]表示第二部分的C變數y,%[value]表示三部分的C變數x;
符號操作符的名字使用了獨立的命名空間。這就意味著它使用的是其他的符號表。簡單一點就是說你不必關心使用的符號名在C代碼中已經使用了。在早期的C代碼中,循環移位的例子必須要這么寫:
asm("mov %0, %1, ror #1" :"=r" (result) : "r" (value))
在匯編代碼中操作數的引用使用的是%後面跟一個數字,%1代表第一個操作數,%2代碼第二個操作數,往後的類推。這個方法目前最新的編譯器還是支持的。但是它不便於維護代碼
實例代碼:
2) 帶.s文件的匯編
編譯命令:
arm-linux-gcc main.cAsmfile_gnu.s -o mains
main.c
#include<stdio.h>
extern voidpcm8_2_pcm16(unsigned char* pIn, int nInlen, short* pOut);
extern voidpcm16_2_pcm8(short* pIn, int nInlen,unsigned char* pOut);
int main()
{
unsigned char* pIn="1234";
short pInd[256];
unsigned char pOutd[256];
int nInlen=4;
int i = 0;
short pOut[256];
for(i=0;i<4;i++)
printf(" 0x%x ",pIn[i]);
printf(" ");
memset((char *)pOut,0,256*2);
memset((char *)pInd,0,256*2);
memset((char *)pOutd,0,256*2);
pcm8_2_pcm16(pIn,nInlen,pOut);
for(i=0;i<4;i++)
printf(" 0x%x ",pOut[i]);
printf(" ");
memcpy((char *)pInd,(char *)pOut,256*2);
pcm16_2_pcm8(pInd,nInlen,pOutd);
for(i=0;i<4;i++)
printf(" 0x%x ",pOutd[i]);
printf(" ");
return 0;
}
Asmfile_gnu.s
.text
.global pcm8_2_pcm16
.global pcm16_2_pcm8
#*******************************#
#********* ENCODER 實現將第一個輸入參數
#左移8位然後異或0x8000 然後拷貝到第三個參數
#DECODE 取第一個參數所指的數據先異或0x8000
#然後右移8位將數據拷貝到第三個參數
#*******************************
pcm8_2_pcm16:
MOV R6,#0
MOV R7,#0
ENCODER:
LDRB R5,[R0,R6]
MOV R8,R5,LSL#8
EOR R9,R8,#0x8000
STRH R9,[R2,R7]
ADD R7,R7,#2
ADD R6,R6,#1
SUB R1,R1,#1
CMP R1,#0
BNE ENCODER
B OVER
pcm16_2_pcm8:
MOV R6,#0
MOV R7,#0
DECODE:
LDRH R5,[R0,R6]
EOR R8,R5,#0x8000
MOV R9,R8,LSR#8
STRB R9,[R2,R7]
ADD R7,R7,#1
ADD R6,R6,#2
SUB R1,R1,#1
CMP R1,#0
BNE DECODE
OVER:
.end
Ⅸ arm匯編裡面,對這處理器的操作可以用c語言嗎比方說這條指令 mcr p15,0, r4,c2,
不可以,這是協處理器指令,不能用c語言只能用匯編