ASM5無(wú)參數化調用C51函數的實(shí)現
MCS -51系列單片機在目前和今后的相當一段時(shí)間內都將是我國的單片機主流機種。但在早期的開(kāi)發(fā)過(guò)程中,程序員不得不從深奧的匯編語(yǔ)言開(kāi)始摸索,同時(shí)要求開(kāi)發(fā)人員對硬件亦有相當的子解。相比而言,專(zhuān)用8051系列單片機設計的Franklin C51語(yǔ)言是一種通用的高級結構化的程序設計語(yǔ)言。入門(mén)容易,程序可讀性強,調試、移植都很方便,故開(kāi)發(fā)效率高,尤其在數值運算處理方便具有很大的優(yōu)勢(這正是ASM51匯編語(yǔ)言的薄弱環(huán)節)。不過(guò),C語(yǔ)言雖然也可對計算機的硬件系統進(jìn)行操作,但在處理特殊I/O口和中斷向量方面,不如匯編那樣直接、有效。因而,在效率為重的今天,將ASM51匯編與C51語(yǔ)言結合起來(lái),充分發(fā)揮各自的優(yōu)勢,無(wú)疑是單片機開(kāi)發(fā)人員的最佳選擇。
1 匯編與C51的混合編程
一般的做法都是利用C51上手容易、便于理解的優(yōu)勢來(lái)編寫(xiě)主程序,在C51語(yǔ)言不便處理或者效率比較低時(shí)調用匯編函數??紤]到MCS-51(尤其是8031 內部的資源配置情況:可用的RAM不到256字節,5個(gè)固定地址的有限中斷源,4個(gè)8位并口中實(shí)際可作I/O口的只有P1口。因而要求開(kāi)發(fā)都對單片機的內部結構有清楚的了解,并盡可能地統籌安排這些資源。事實(shí)也證明,不理解匯編語(yǔ)言是很難寫(xiě)出高效程序的。故筆者的觀(guān)點(diǎn)是利用匯編語(yǔ)言對I/O接口、中斷向量及程序空間分配的茂大優(yōu)勢,讓程序員對MCS-51內的第一個(gè)字節甚至是每一比特(可位尋址的空間)全部進(jìn)行統籌安排,設計好各個(gè)程序模塊,包括I/O口地址和中斷向量地址的處理;同時(shí)在具體的數據處理、通信等不需要過(guò)多與硬件直接打交道的程序模塊中,充分利用C51語(yǔ)言強大高效的編程能力。
最后的關(guān)鍵是如何讓匯編模塊能正確識別C51函數并調用它來(lái)完成相應的功能。ASM51匯編與C51 語(yǔ)言之間的調用約定并不簡(jiǎn)單,而且各種編譯器使用的約定不盡相同,甚至還依賴(lài)于程序所選擇的大、中、小存儲模式。通常每個(gè)需傳遞的參數按調用順序和類(lèi)型分別由約定的寄存器來(lái)傳遞。如果參數過(guò)多或者無(wú)足夠寄存器可用時(shí),參數的傳遞將在固定持存儲器區域內進(jìn)行,相同類(lèi)型的參數共享一個(gè)參數傳遞段,按參數調用順序遞增其存放地址,返回值也由約定的寄存器或地址段返回。由此可見(jiàn)程序調用的效率必將受到接口復雜度的影響。盡管目前的單片機仿真器已經(jīng)提供了標準接口的全自動(dòng)轉換功能,減少了接口工作量,但在程序的調試及移植中,如果程序員不了解這些接口的各種約定,將對出現的錯誤不知所措。比如返回值不止一個(gè)時(shí),編譯器自己就無(wú)法正確完成接口配置。這里力薦一種簡(jiǎn)潔有效的調用方法——無(wú)參數化調用。
2 ASM51無(wú)參數化調用C51函數的實(shí)現原理
所謂的無(wú)參數化調用是指讓C51子函數不帶任何參數,這樣就可以從根本上避開(kāi)調用參數的傳遞和返回值的安排等繁瑣易出錯的問(wèn)題,只需要簡(jiǎn)單地在匯編語(yǔ)言開(kāi)頭說(shuō)明一下外部C51子函數(“EXTRN code(C51模塊名稱(chēng)>)”)。至于C51函數中需要使用的外部參數值及其返回值,完全可以通過(guò)加入C51 的absacc.h>頭文件來(lái)解決。
absacc.h>頭文件中的函數原型為:
# define CBYTE((unsigned char *)0x50000L)
# define DBYTE ((unsigned char *)0x50000L)
# define PBYTE ((unsigned char *)0x50000L)
# define XBYTE((unsigned char *)0x50000L)
其中CBYTE定義為尋址CODE程序區;DBYTE定義為尋址DATA數據區;PBYTE定義為尋址相對于MOVX @R0"指令的分頁(yè)數據XDATA區;XBYTE定義為尋址相對于MOVX @DPTR"指令的分布數據XDATA區。它們的類(lèi)型決定了絕對地址空間的位置。
引進(jìn)該頭文件后,程序員就可以對8051系列單片機的存儲器進(jìn)行絕對地址的訪(fǎng)問(wèn),把對參數值和返回值的操作轉化為對存儲器絕對地址的操作,像純匯編操作一樣,根本不用定義C51函數與匯編接口的參數和返回值的配置,從而提高了調用效率。具體做法是:先在 C51函數中定義好傳遞參數和返回值所需要的各個(gè)絕對地址(視程序員自己的空間配置而定),在其它匯編模塊中將C51函數中將要使用的參數值放入這些絕對地址中,把被調用C51模塊將輸出的計算值(可以不止一個(gè))也放入類(lèi)似的絕對地址中。于是,當C51函數中需要使用某個(gè)參數值時(shí),就直接從相應的絕對地址中讀取該值;當別的匯編模塊中需要使用C51函數返回值時(shí),也直接對存放返回值的絕對地址進(jìn)行讀操作即可。下面以一個(gè)調試通過(guò)的匯編調用C51函數的簡(jiǎn)單程序為例進(jìn)行具體說(shuō)明。
3 ASM51無(wú)參數化調用C51函數的實(shí)現示例
該系統要示然而單片機根據實(shí)時(shí)采樣輸入的轉速實(shí)現機車(chē)速度的測量,并可隨鍵盤(pán)輸入的車(chē)輪直徑變化實(shí)時(shí)調整車(chē)速,最后將車(chē)速和輪徑值都顯示出來(lái)。設計任務(wù)很簡(jiǎn)單,編程中的最大難度就在于車(chē)速的計算程序。由于輪徑值要求精確到mm(最大值超過(guò)了1000),車(chē)速的計算結果要保留到小數點(diǎn)后一位,因此需要進(jìn)行浮點(diǎn)數運算,期間還要完成數的各種進(jìn)制間的換算。雖然算法簡(jiǎn)單,但實(shí)際用匯編語(yǔ)言實(shí)現起來(lái)經(jīng)??紤]不周,調試起來(lái)費時(shí)費力(筆者調試通過(guò)的這段匯編代碼長(cháng)達近 400行)。這樣,自然就想到調用C51函數了,充發(fā)發(fā)揮兩種語(yǔ)言的優(yōu)勢。先用匯編語(yǔ)言設計好各個(gè)模塊,包括循環(huán)顯示車(chē)速和輪徑值的主程序模塊,響應采樣轉速值和鍵盤(pán)輸入兩個(gè)中斷模塊,代碼如下所示。
EXTRN CODE(CALL1) ;聲明外部C51函數
ORG 0000H
LJMP MAIN
ORG 0003H
AJMP KEYINPUT ;鍵盤(pán)輸入中斷
ORG 000BH
AJMP SETTIME ;采樣時(shí)間到,采樣轉速值中斷
ORG 0100H
KEYINPUT:…… ;鍵盤(pán)輸入中斷
…… ;將鍵盤(pán)輸入信號保存在
;70h~73h的地址空間中
RETI
ORG 0600H
SETTIME:…… ;采樣時(shí)間到,采樣轉速值中斷
…… ;將轉速值放置在地址為3Ah的空間中
;緊接著(zhù)調用外部C51函數CALL1()進(jìn)
;行車(chē)速的計算
LCALL CALL1
RETI
ORG 2000H ;主程序模塊
MAIN:…… ;首先進(jìn)行初始化操作
……
;直接從地址空間70h~77h中讀取顯示數據,循環(huán)顯示車(chē)速和輪徑值
END
評論