《電子技術應用》
您所在的位置:首頁 > 嵌入式技術 > 業界動態 > ASM51無參數化調用C51函數的實現

ASM51無參數化調用C51函數的實現

2009-01-13
作者:茍 帥

  摘? 要: 利用匯編模塊對C51模塊進行無參數化調用,從根本上避開了傳統匯編模塊和C51模塊之間調用時的繁瑣接口編程問題,并以實例驗證了該方法的優越性和有效性。

  關鍵詞: ASM51匯編語言? C51語言? 無參數化調用

?

  MCS-51系列單片機在目前和今后的相當一段時間內都將是我國的單片機主流機種。但在早期的開發過程中,程序員不得不從深奧的匯編語言開始摸索,同時要求開發人員對硬件亦有相當的了解。相比而言,專為8051系列單片機設計的Franklin C51語言是一種通用的高級結構化的程序設計語言。入門容易,程序可讀性強,調試、移植都很方便,故開發效率高,尤其在數值運算處理方面具有很大的優勢(這正是ASM51匯編語言的薄弱環節)。不過,C語言雖然也可對計算機的硬件系統進行操作,但在處理特殊I/O口和中斷向量方面,不如匯編那樣直接、有效。因而,在效率為重的今天,將ASM51匯編與C51語言結合起來,充分發揮各自的優勢,無疑是單片機開發人員的最佳選擇。

1 匯編與C51的混合編程

  一般的做法都是利用C51上手容易、便于理解的優勢來編寫主程序,在C51語言不便處理或者效率比較低時調用匯編函數。考慮到MCS-51(尤其是8031)內部的資源配置情況:可用的RAM不到256字節,5個固定地址的有限中斷源,4個8位并口中實際可作I/O口的只有P1口。因而要求開發者對單片機的內部結構有清楚的了解,并盡可能地統籌安排這些資源。事實也證明,不理解匯編語言是很難寫出高效程序的。故筆者的觀點是利用匯編語言對I/O接口、中斷向量及程序空間分配的巨大優勢,讓程序員對MCS-51內的每一個字節甚至是每一比特(可位尋址的空間)全部進行統籌安排,設計好各個程序模塊,包括I/O口地址和中斷向量地址的處理;同時在具體的數據處理、通信等不需要過多與硬件直接打交道的程序模塊中,充分利用C51語言強大高效的編程能力。

  最后的關鍵是如何讓匯編模塊能夠正確識別C51函數并調用它來完成相應的功能。ASM51匯編與C51語言之間的調用約定并不簡單,而且各種編譯器使用的約定不盡相同,甚至還依賴于程序所選擇的大、中、小存儲模式。通常每個需傳遞的參數按調用順序和類型分別由約定的寄存器來傳遞。如果參數過多或者無足夠寄存器可用時,參數的傳遞將在固定的存儲器區域內進行,相同類型的參數共享一個參數傳遞段,按參數調用順序遞增其存放地址,返回值也由約定的寄存器或地址段返回。由此可見程序調用的效率必將受到接口復雜度的影響。盡管目前的單片機仿真器已經提供了標準接口的全自動轉換功能,減少了接口工作量,但在程序的調試及移植中,如果程序員不了解這些接口的各種約定,將對出現的錯誤不知所措。比如返回值不止一個時,編譯器自己就無法正確完成接口配置。這里力薦一種簡潔有效的調用方法——無參數化調用。

2 ASM51無參數化調用C51函數的實現原理

  所謂的無參數化調用是指讓C51子函數不帶任何參數,這樣就可以從根本上避開調用參數的傳遞和返回值的安排等繁瑣易出錯的問題,只需要簡單地在匯編語言開頭說明一下外部C51子函數(“EXTRN? code()”)。至于C51函數中需要使用的外部參數值及其返回值,完全可以通過加入C51的 頭文件來解決。

  頭文件中的函數原型為:

  # 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″指令的分頁數據XDATA區;XBYTE定義為尋址相對于MOVX @DPTR″指令的分頁數據XDATA區。它們的類型決定了絕對地址空間的位置。

  引進該頭文件后,程序員就可以對8051系列單片機的存儲器進行絕對地址的訪問,把對參數值和返回值的操作轉化為對存儲器絕對地址的操作,像純匯編操作一樣,根本不用定義C51函數與匯編接口的參數和返回值的配置,從而提高了調用效率。具體做法是:先在C51函數中定義好傳遞參數和返回值所需要的各個絕對地址(視程序員自己的空間配置而定),在其它匯編模塊中將C51函數中將要使用的參數值放入這些絕對地址中,把被調用C51模塊中將輸出的計算值(可以不止一個)也放入類似的絕對地址中。于是,當C51函數中需要使用某個參數值時,就直接從相應的絕對地址中讀取該值;當別的匯編模塊中需要使用C51函數的返回值時,也直接對存放返回值的絕對地址進行讀操作即可。下面以一個調試通過的匯編調用C51函數的簡單程序為例進行具體說明。

3 ASM51無參數化調用C51函數的實現示例

  該系統要求用單片機根據實時采樣輸入的轉速實現機車速度的測量,并可隨鍵盤輸入的車輪直徑變化實時調整車速,最后將車速和輪徑值都顯示出來。設計任務很簡單,編程中的最大難度就在于車速的計算程序。由于輪徑值要求精確到mm(最大值超過了1000),車速的計算結果要保留到小數點后一位,因此需要進行浮點數運算,期間還要完成數的各種進制間的換算。雖然算法簡單,但實際用匯編語言實現起來經常考慮不周,調試起來費時費力(筆者調試通過的這段匯編代碼長達近400行)。這樣,自然就想到調用C51函數了,充分發揮兩種語言的優勢。先用匯編語言設計好各個模塊,包括循環顯示車速和輪徑值的主程序模塊,響應采樣轉速值和鍵盤輸入兩個中斷模塊,代碼如下所示。

  EXTRN CODE (CALL1)????????????????? ;聲明外部C51函數

    ORG 0000H

    LJMP MAIN

    ORG 0003H???

    AJMP? KEYINPUT  ????????????? ;鍵盤輸入中斷

    ORG 000BH?????

    AJMP SETTIME????       ? ;采樣時間到,采樣轉速值中斷

    ORG? 0100H

  KEYINPUT:……??? ???? ????????? ?? ;鍵盤輸入中斷????

?????????????……?????  ??????????????;將鍵盤輸入信號保存在

????????????????????????????????????????;70h~73h的地址空間中

    RETI????????

    ORG 0600H

    SETTIME:……?         ? ;采樣時間到,采樣轉速值中斷

??????? ?????? ……?????????????    ;將轉速值放置在地址為3Ah的空間中

?????????????????????????      ?? ;緊接著調用外部C51函數CALL1()進

???????????????????????????       ;行車速的計算

  LCALL CALL1??????????

  RETI

  ORG?? 2000H?? ????       ??? ;主程序模塊

  MAIN: ......????????????????????????;首先進行初始化操作

?????? ?? ......??

????????????????????????????????????????;直接從地址空間70h~77h中讀取顯示數據,循環顯示車速和輪徑值

  END

  這些小模塊用匯編實現起來不僅容易,而且程序員可以清楚地了解到各個模塊的出入口及其相應的功能,實現對程序空間的充分配置。最后用C51語言來實現車速的計算模塊CALL1()。以前用匯編編寫的近400行代碼,一下子被壓縮到20~30行(真正的計算代碼僅9行),不僅簡短易懂,而且幾乎就不需要調試了。

  下面的代碼是計算模塊CALL1()及其需要的絕對地址定義。

#pragma code small

#include

#include

#define PI 3.1415926

#define? NCIRCLE DBYTE[0x3A]?? ;定義放置轉速的絕對地址

#define? DIRECT1 DBYTE[0x70]?? ;定義放置輪徑千位的絕對地址

#define? DIRECT2 DBYTE[0x71]?? ;定義放置輪徑百位的絕對地址

#define? DIRECT3 DBYTE[0x72]?? ;定義放置輪徑十位的絕對地址

#define? DIRECT4 DBYTE[0x73]?? ;定義放置輪徑個位的絕對地址

#define? VELOCITY1 DBYTE[0x74] ;定義返回車速的千位絕對地址

#define? VELOCITY2 DBYTE[0x75] ;定義返回車速的百位絕對地址

#define? VELOCITY3 DBYTE[0x76] ;定義返回車速的十位絕對地址

#define? VELOCITY4 DBYTE[0x77]?;定義返回車速的個位絕對地址

void call1( )

{

?????? float data result;

?????? int data DIRECT;

?????? DIRECT=DIRECT1*1000+DIRECT2*100+DIRECT3*10

??????????? +DIRECT4;

?????? result=(DIRECT/1000.0)*PI*NCIRCLE*3.6;

?????? VELOCITY1=result/100;

?????? result=result-VELOCITY1*100;

?????? VELOCITY2=result/10;

?????? result=result-VELOCITY2*10;

?????? VELOCITY3=result;

?????? result=result-VELOCITY3;

?????? VELOCITY4=result*10;

}

??? 在本例中定義了絕對地址空間70H~77H和3AH。其中3AH存放采樣轉速值輸入模塊輸入的轉速;70H~73H的地址空間中存放鍵盤輸入中斷模塊中鍵盤輸入的輪徑值;而地址為74H~77H的空間中則存放計算模塊中的車速計算返回值。盡管需要傳遞

和返回的參數比較多,但通過這些絕對地址的定義,完全解決了原來復雜的匯編與C51之間的調用接口配置。計算模塊中需要使用轉速和輪徑值時,將自動從絕對地址3AH和70H~73H中取值;在循環顯示車速和輪徑值的主程序模塊中則直接讀取絕對地址空間70H~77H的各個數據進行循環顯示。當然,程序員可以根據自己的空間配置另外定義這些絕對地址。

以上程序代碼均已在Dais-52.196P仿真器上順利調試通過。

  由上面的簡單程序可以看出這種無參數化調用方法的優越性和有效性:從程序代碼看,無論是編寫C51子程序還是匯編主程序,都與編寫純C51函數或者純匯編主程序的格式完全一樣,從根本上簡化了C51與匯編函數之間的接口編程,提高了程序調用的效率;充分利用了匯編與高級C51語言各自的優點,開發、調試快速方便,通用性強,尤其適合于初學者。對于復雜程序,同樣可以利用無參數化方法來幫助實現。這對于提高單片機應用程序的開發效率很有意義。

  無參數化調用實質上在C51函數中定義了幾個全局變量(絕對地址),依靠它們直接完成參數值的傳遞和返回值的調用,相當于一種程序員自定義的傳遞方式,拋棄了傳統C與匯編之間的接口約定。只要程序員安排得當,還可以進一步人工實現C51中的動態覆蓋重用,提高RAM區的利用效率。由上也可看出:無參數化調用方法要在ASM匯編調用C51函數時才能充分發揮其巨大優勢;如果全部采用C51編程,過分依賴無參數化思想,就違背了利用匯編優勢的初衷,得不償失。當然,如果開發人員已經對C51與匯編函數之間的參數傳遞接口很熟悉,完全可以按接口約定或者由編譯器自動完成參數的傳遞。

?

參考文獻

1 徐愛鈞.彭秀華.單片機高級語言C51應用程序設計.北京:電子工業出版社,1998

2 Dais系列組合式仿真編程器使用手冊.1999

本站內容除特別聲明的原創文章之外,轉載內容只為傳遞更多信息,并不代表本網站贊同其觀點。轉載的所有的文章、圖片、音/視頻文件等資料的版權歸版權所有權人所有。本站采用的非本站原創文章及圖片等內容無法一一聯系確認版權者。如涉及作品內容、版權和其它問題,請及時通過電子郵件或電話通知我們,以便迅速采取適當措施,避免給雙方造成不必要的經濟損失。聯系電話:010-82306118;郵箱:aet@chinaaet.com。
主站蜘蛛池模板: 亚洲成a人片77777在线播放 | 国产综合第一页在线视频 | 99久久国产免费中文无字幕 | 九九热视频免费在线观看 | 久久伊人免费视频 | 欧美在线观看视频一区 | 国产日韩欧美视频在线观看 | 女兵人3未删减版在线观看 暖暖喜欢你电视剧免费观看完整版高清 | 99ri国产在线 | 日韩福利在线观看 | 欧美色第一页 | 亚洲精品午夜国产va久久 | 天天躁夜夜躁狠狠躁 | 99在线视频精品费观看视 | 久久久综合中文字幕久久 | 国产欧美日韩不卡 | 亚洲色图激情文学 | 好姑娘中文在线播放 | 欧美五月婷婷 | 国产美女动态免费视频 | 国产精品视频永久免费播放 | 国产免费爱在线观看视频 | 热久久国产| 99视频在线观看免费视频 | 久久成人免费网站 | 欧美日韩另类在线观看视频 | 免费看国产精品久久久久 | 国产99在线视频 | 精品小视频在线 | 免费永久观看美女视频网站网址 | 久久国语精品 | 国产99热| 免费国产午夜高清在线视频 | 精品一区二区三区四区五区六区 | 久久九九免费 | 色在线视频网站 | 亚洲人人视频 | 黄色成人在线观看 | 免费成人黄色网址 | 日韩欧美亚洲国产精品字幕久久久 | 99热这里只有精品久久免费 |