|
C51編譯器能對(duì)C語(yǔ)言程序進(jìn)行高效率的編譯,生成高效簡(jiǎn)潔的代碼,在大多數(shù)的應(yīng)用場(chǎng)合,采用C語(yǔ)言編程即可完成預(yù)期的任務(wù),但是,在有些場(chǎng)合還是會(huì)用到匯編,例如在下面的幾種情況下,采用匯編可能會(huì)有很多好處:
1、已有程序的移植:在單片機(jī)領(lǐng)域工作很久的工程人員可能會(huì)保留有很多的早期用匯編語(yǔ)言編制的程序模塊,并且這些模塊已經(jīng)經(jīng)過(guò)實(shí)際應(yīng)用的驗(yàn)證,如果重新用C編程,可能工作量很大,這時(shí)就可以用嵌入?yún)R編的方式把以前的匯編模塊植入新的應(yīng)用,可以明顯的加快開(kāi)發(fā)的進(jìn)度。
2、局部功能需要足夠短的執(zhí)行時(shí)間:在有些應(yīng)用中,部分的功能模塊需要有很高的執(zhí)行效率,而有些匯編的指令在C中沒(méi)有對(duì)應(yīng)的指令,這給我們對(duì)單片機(jī)的高效操作帶來(lái)困難,嵌入?yún)R編可是我們的程序執(zhí)行更有效率。
3、對(duì)一些特定地址進(jìn)行操作:在C中我們要對(duì)特定地址進(jìn)行讀寫(xiě),一般用以下兩種方式:用_AT_指令定義變量;定義指向外部端口或數(shù)據(jù)地址的指針;在匯編中只需要使用MOVX A,@DPTR或MOVX @DPTR,A就可以了,這樣可以增強(qiáng)程序的可讀性。
4、其他的需要匯編的應(yīng)用:在這里我們不可能舉出所有可能要用匯編的例子,在你的應(yīng)用中,你可能在一個(gè)或多個(gè)應(yīng)用中感到C語(yǔ)言的不足,而需要用到匯編指令,請(qǐng)你記住,可以在C中嵌入?yún)R編子程序,這對(duì)你的程序非常有用。
首先介紹一下調(diào)用匯編的參數(shù)傳遞規(guī)則,見(jiàn)下表
| 傳遞的參數(shù)
| char、1字節(jié)指針
| int、2字節(jié)指針
| long、float
| 一般指針 |
| 第一個(gè)參數(shù)
| R7
| R6,R7
| R4~R7
| R1,R2,R3 |
| 第二個(gè)參數(shù)
| R5
| R4,R5
|
| R1,R2,R3 |
| 第三個(gè)參數(shù)
| R3
| R2,R3
| 無(wú)
| R1,R2,R3 |
在下面的例子中我們首先給出一個(gè)C程序調(diào)用匯編的例子,先說(shuō)明一下,在這個(gè)例子中,你完全可以用C完成,我用這個(gè)例子,只是為了說(shuō)明嵌入?yún)R編的方法。
例1:
下面是C語(yǔ)言的主程序
#include <REG52.H> #include <stdio.h> extern char asm(char c,char b); bit VAL; void main (void) { char out=0x49; char direct; char key; SCON =0x50; /* SCON: mode 1, 8-bit UART, enable rcvr */ TMOD |=0x20; /* TMOD: timer 1, mode 2, 8-bit reload */ TH1 =0xfd; /* TH1: reload value for 9600 baud @ 11.0592MHz */ TR1 =1; TI =1; /* TI: set TI to send first char of UART */ VAL=0; while (1) { key=getchar(); if(key=='R') { direct=0X01; out=asm(out,direct); printf ("Right rotate\n"); } if(key=='L') { direct=0X02; out=asm(out,direct); printf ("Left rotate\n"); } printf("%bx\n",out); } }
下面是匯編的子程序(文件名稱(chēng)asmtest.asm)
NAME ASM ?PR?_asm?ASMTEST SEGMENT CODE ?BI?_asm?ASMTEST SEGMENT BIT PUBLIC ?_asm?BIT PUBLIC _asm RSEG ?BI?_asm?ASMTEST ?_asm?BIT: VAL: DBIT 1 RSEG ?PR?_asm?ASMTEST _asm: MOV A,R7 MOV C,VAL DJNZ R5,JP1 RRC A JP1: DJNZ R5,JP2 RLC A JP2: MOV 90h,A MOV R7,A MOV VAL,C RET END
現(xiàn)在對(duì)這個(gè)例子簡(jiǎn)短的說(shuō)明,這個(gè)例子是用來(lái)驅(qū)動(dòng)一個(gè)不帶細(xì)分的三相步進(jìn)電機(jī),用的是循環(huán)移位的指令來(lái)實(shí)現(xiàn)的,由于一個(gè)字節(jié)是8位,如果算上進(jìn)位位,共9位,通過(guò)付值,可以得到這樣的數(shù)100100100,大家可以看到任意取中間的3位,相鄰的每3位與它都一樣,這樣我們就可以去中間的3位輸出到端口去驅(qū)動(dòng)一個(gè)三相的步進(jìn)電機(jī),通過(guò)對(duì)這個(gè)9位的二進(jìn)制數(shù)進(jìn)行循環(huán)移位,可以實(shí)現(xiàn)電機(jī)的步進(jìn),在51系列單片機(jī)中有兩條指令可以幫助我們進(jìn)行循環(huán)移位操作,這就是RRC A和RLC A指令,我們只要把第九位保存好,在需要移位操作時(shí),把它付給PSW中C,再執(zhí)行循環(huán)移位就可以了。
在這個(gè)例子中,我發(fā)現(xiàn)了幾個(gè)需要注意的地方:
1、在C程序中,我不能把VAL變量設(shè)為extern類(lèi)型,否則在連接時(shí)會(huì)有警告,導(dǎo)致數(shù)值不能傳遞;
2、在匯編模塊中,不能把SEGMENT BIT段置為OVERLAYABLE即可覆蓋段,如果置為可覆蓋段,那么在進(jìn)入?yún)R編模塊時(shí)VAL變量值丟失;
3、如果把VAL變量作為函數(shù)的參數(shù)傳遞,出現(xiàn)在返回后在執(zhí)行printf函數(shù)后變量值丟失;
上面是本人寫(xiě)的一個(gè)C程序調(diào)用匯編的小例子,在本例中的幾個(gè)printf函數(shù)是為了便于在Keil C51中模擬調(diào)試時(shí)觀察運(yùn)行結(jié)果的,在實(shí)際應(yīng)用中可以將這幾條去掉,這只是一個(gè)簡(jiǎn)短的示例,目的在于介紹一下C調(diào)用匯編的用法,希望對(duì)大家有幫助,同時(shí)由于本人水平有限,在程序中有些地方可能仍有不周到之處,歡迎廣大單片機(jī)高手不吝指出。 |