keil4内嵌汇编_keil C中嵌入汇编程序的方法
void main(void)
{
P2=1;
#pragma asm
MOV R7,#10
DEL:MOV R6,#20
DJNZ R6,$
DJNZ R7,DEL
#pragma endasm
P2=0;
}
2 . 無參數(shù)傳遞的函數(shù)調(diào)用
C51調(diào)用匯編函數(shù)
1.無參數(shù)傳遞的函數(shù)調(diào)用
先來個例子:其中example.c和example.a51為項目中的兩個文件
***********************example.c***********************************************
extern void delay100();
main()
{delay100;}
***********************example.a51***********************************************
PR?DELAY100 SEGMENT CODE; //? 在程序存儲區(qū)中定義段
PUBLIC DELAY100;???? //聲明函數(shù)
RSEG ?PR?DELAY100;??? //函數(shù)可被連接器放置在任何地方
DELAY100:
MOV R7,#10
DEL:
MOV R6,#20
DJNZ R6,$
DJNZ R7,DEL
RET
END
在example.c文件中,先聲明外部函數(shù),然后直接在main中調(diào)用即可。
在example.a51中,
PR?DELAY100 SEGMENT CODE;? 作用是在程序存儲區(qū)中定義段,DELAY100為段名,?PR?表示段位于程序存儲區(qū)內(nèi)
PUBLIC DELAY100;???? 作用是聲明函數(shù)為公共函數(shù)
RSEG ?PR?DELAY100;??? 表示函數(shù)可被連接器放置在任何地方,RSEG是段名的屬性
段名的開頭為PR,是為了和C51內(nèi)部命名轉(zhuǎn)換兼容,命名轉(zhuǎn)換規(guī)律如下:
CODE -?PR?
XDATA-?XD
DATA-?DT
BIT-?BI
PDATA-?PD
3. 有參數(shù)傳遞的函數(shù)調(diào)用
在寫這片文章之前,寫了個試驗程序,但總是通不過,查看匯編代碼發(fā)現(xiàn)c文件中的語句根本沒有被編譯進去,怎么也找不到原因,郁悶
~~
最后在網(wǎng)上搜了個試驗程序,把我的程序復(fù)制過去,可以編譯成功,奇怪了,在我的project里就是不行,我注意到我的project編譯后
出現(xiàn)一條WARNING:
*** WARNING L7: MODULE >??? MODULE:? 8.obj (8)
而同樣的程序代碼在另外一個project中沒有WARNING,肯定是這條WARNING語句導(dǎo)致的,里面提到NAME,難道和名字有關(guān),馬上把A51文
件改個名字(原來c文件和a51文件名字一樣),編譯,哈哈,WARNING不見了,查看匯編代碼,一切按預(yù)想的進行,唉,一個名字害得我不淺啊
,記住哦,c文件和A51文件不能使用同一個文件名,不過我還不知道為什么會這樣,有高手知道得話請告知,還是進行今天的作業(yè)吧!
今天說說帶參數(shù)傳遞的函數(shù)調(diào)用,在C51和匯編之間傳遞參數(shù)的方式有兩種,一種是通過寄存器傳遞參數(shù),C51中不同類型的實參會存入
相應(yīng)的寄存器,在匯編中只需對相應(yīng)寄存器進行操作,即達到傳遞參數(shù)的目的。
不同類型的數(shù)據(jù)及其傳遞參數(shù)的寄存器如下表所示:
參數(shù)類型 char int long/float 通用指針
第1個 R7 R6&R7 R4-R7 R1-R3
第2個 R5 R4&R5 R4-R7 R1-R3
第3個 R3 R2&R3 -- R1-R3
舉個例子吧,void delay(unsigned char i, unsigned int j)? 當執(zhí)行語句delay(10,1000)時,10會存入R7中,1000高位會存入R4中
,低位存入R5中。在匯編語句中從這幾個寄存器中取數(shù),再進行操作就行了,說起來也很簡單的嘛,呵呵~
來個最簡單的實例吧,沒什么意義,傻瓜式的程序:
****************************main.c*********************************************
extern void DELAY(unsigned char i,unsigned int j);
main()
{
DELAY(10,1000);
while(1);
}
**********************DELAY.A51********************************************
PR?_DELAY?DELAY???? SEGMENT CODE
PUBLIC _DELAY
RSEG? ?PR?_DELAY?DELAY
_DELAY:
DJNZ R4,$
DJNZ R5,$
DJNZ R7,$
RET
END
還要說的是,函數(shù)名前要加下劃線,表示是有參數(shù)傳遞的函數(shù)調(diào)用!
4. 函數(shù)的返回值傳遞參數(shù)
(2)函數(shù)返回值所用的寄存器
返回值類型 寄存器 說明
Bit C 由具體標志位返回
char/unsigned char / 1 byte 指針 R7
int/unsigned int / 2 byte 指針 R6&R7 高位在R6
long/unsigned long / 3 byte 指針 R4-R7 高位在R4
float R4-R7 32bit IEEE格式,指數(shù)和符號位在R7
通用指針 R1-R3 存儲類型在R3,高位在R2
實例:
********************main.c****************************************
unsigned int example(unsigned char i)
{
return(i*i);
}
main()
{example(80);
#pragma asm
DJNZ R7,$
DJNZ R6,$
#pragma endasm
while(1);
}
函數(shù)返回值在R6,R7中。
有時候用到需要精確延時之類的子程序時,用C語言比較難控制,這時候就可以在C中嵌入?yún)R編
比較常用的keil中嵌入?yún)R編的方法如下所示:
如圖一,在C文件中要嵌入?yún)R編的地方用#pragma asm和#pragma endasm分隔開來,這樣編譯時KEIL就知道這中間的一段是匯編了。
在有加入?yún)R編的文件中,還要設(shè)置編譯該文件時的選項
Generate Assembler SRC File 生成匯編SRC文件
Assemble SRC File 封裝匯編文件
(如圖三的狀態(tài)為選中)
選上這兩項就可以在C中嵌人匯編了,設(shè)置后在文件圖示中多了三個紅色的小方塊。
為了能對匯編進行封裝還要在項目中加入相應(yīng)的封裝庫文件, 在筆者的項目中編譯模式是小模式所以選用C51S.LIB。這也是最常用的。這些庫
文件是中KEIL安裝目錄下的LIB目錄中。 加好后就可以順利編譯了。(注:我只在7.0以上版本使用過)
匯編與C語言混合編程的關(guān)鍵問題
1 C程序變量與匯編程序變量的共用
為了使程序更易于接口和維護,可以在匯編程序中引用與C程序共享的變量:
.ref_to_dce_num,_to-dte_num,_to_dce_buff,_to_dte_buff
在匯編程序中引用而在C程序可直接定義的變量:
unsigned char to_dte_buff[BUFF_SIZE];???? //DSP發(fā)向PC機的數(shù)據(jù)
int to_dte_num;?????????????????????????? //緩沖區(qū)中存放的有效字節(jié)數(shù)
int to_dte_store;???????????????????????? //緩沖區(qū)的存放指針
int to_dte_read;????????????????????????? //緩沖區(qū)的讀取指針
這樣經(jīng)過鏈接就可以完成對應(yīng)。
2 程序入口問題
在C程序中,程序的入口是main()函數(shù)。而在匯編程序中其入口由*.cmd文件中的命令決定,如:-e main_start;程序入口地址為 main
_start。這樣,混合匯編出來的程序得不到正確結(jié)果。因為C到ASM的匯編有默認的入口c-int00,從這開始的一段程序為C程序的運行做準備工
作。這些工作包括初始化變量、設(shè)置棧指針等,相當于系統(tǒng)殼不能跨越。這時可在*.cmd文件中去掉語句:-e main_start。如仍想執(zhí)行某些匯
編程序,可以C函數(shù)的形式執(zhí)行,如:
main_start();???????????? //其中含有其他匯編程序
但前提是在匯編程序中把_main_start作為首地址,程序以rete結(jié)尾(作為可調(diào)用的函數(shù))的程序段,并在匯編程序中引用_main_start,
即.ref _main_start。
3 移位問題
在C語言中把變量設(shè)為char型時,它是8位的,但在DSP匯編中此變量仍被作為16位處理。所以會出現(xiàn)在C程序中的移位結(jié)果與匯編程序移位
結(jié)果不同的問題。解決的辦法是在C程序中,把移位結(jié)果再用0X00FF去“與”一下即可。
4 堆棧問題
在匯編程序中對堆棧的依賴很小,但在C程序中分配局部變量、變量初始化、傳遞函數(shù)變量、保存函數(shù)返回地址、保護臨時結(jié)果功能都是靠
堆棧完成。而C編譯器無法檢查程序運行時堆棧能否溢出。
5 程序跑飛問題
編譯后的C程序跑飛一般是對不存在的存儲區(qū)訪問造成的。首先要查.MAP文件與memory map圖對比,看是否超出范圍。如果在有中斷的程序
中跑飛,應(yīng)重點查在中斷程序中是否對所用到的寄存器進行了壓棧保護。如果在中斷程序中調(diào)用了C程序,則要查匯編后的C程序中是否用到了
沒有被保護的寄存器并提供保護(在C程序的編譯中是不對A、B等寄存器進行保護的)。
新人創(chuàng)作打卡挑戰(zhàn)賽發(fā)博客就能抽獎!定制產(chǎn)品紅包拿不停!總結(jié)
以上是生活随笔為你收集整理的keil4内嵌汇编_keil C中嵌入汇编程序的方法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: OpenMP基本概念
- 下一篇: 不用空格怎么打两个空格_和平精英:苹果手