C51中變量和函數(shù)的絕對(duì)地址定位問(wèn)題_第1頁(yè)
C51中變量和函數(shù)的絕對(duì)地址定位問(wèn)題_第2頁(yè)
C51中變量和函數(shù)的絕對(duì)地址定位問(wèn)題_第3頁(yè)
C51中變量和函數(shù)的絕對(duì)地址定位問(wèn)題_第4頁(yè)
C51中變量和函數(shù)的絕對(duì)地址定位問(wèn)題_第5頁(yè)
已閱讀5頁(yè),還剩25頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、C51中變量和函數(shù)的絕對(duì)地址定位問(wèn)題:1.變量絕對(duì)地址定位1)在定義變量時(shí)使用_at_關(guān)鍵字加上地址就可.e.g.unsigned char idata myvar _at_ 0x40;把變量myvar定義在idata的0x40處,在M51文件中可以找到這麼一行IDATA0040H0001HABSOLUTE表示有變量在idata的0x0040處絕對(duì)地址定位.2)使用KeilC編譯器定義絕對(duì)地址的變量,方法待查.2.函數(shù)絕對(duì)地址定位1)在程序中編寫一函數(shù)myTestvoid myTest(void)/ Add your code here2)使用KeilC編譯器定位絕對(duì)地址的函數(shù),打開(kāi)Proje

2、ct - Options for Target菜單,選中BL51 Locate選項(xiàng)卡,在Code:中輸入:?PR?myTest?MAIN(0x4000)把函數(shù)myTest定位到程序區(qū)的0x4000處,再次編譯就可以了.3)一次定位多個(gè)函數(shù)的方法同樣地,在程序中再編寫另外一個(gè)函數(shù)myTest1void myTest1(void)/ Add your code here在Options for Target菜單的BL51 Locate選項(xiàng)卡的Code:中輸入:?PR?myTest1?MAIN(0x3900), ?PR?myTest?MAIN(0x4000)把函數(shù)myTest1定位在程序區(qū)的0x39

3、00處,把函數(shù)myTest定義在程序區(qū)的0x4000處,重新編譯就可以了.在M51文件中可以找到下面的內(nèi)容: 3.obj TO Reader RAMSIZE (256) CODE (?PR?MYTEST1?MAIN (0X3900), ?PR?MYTEST?MAIN(0X4000)3665H029BH* GAP *CODE3900H0014HUNIT?PR?MYTEST1?MAIN3914H06ECH* GAP *CODE4000H0014HUNIT?PR?MYTEST?MAIN4)函數(shù)的調(diào)用:程序中直接調(diào)用函數(shù)的方式就不說(shuō)明了,這里重點(diǎn)講使用函數(shù)指針調(diào)用絕對(duì)地址處的函數(shù)的方法.(1)定義調(diào)用

4、的函數(shù)原形typedef void (*CALL_MYTEST)(void);這是一個(gè)回調(diào)函數(shù)的原形,參數(shù)為空.(2)定義相應(yīng)的函數(shù)指針變量CALL_MYTESTmyTestCall = NULL;(3)函數(shù)指針變量賦值,指向我們定位的絕對(duì)地址的函數(shù)myTestCall = 0x3900;指向函數(shù)myTest1(4)函數(shù)指針調(diào)用if (myTestCall != NULL)myTestCall();/調(diào)用函數(shù)指針處的函數(shù)myTest1,置PC指針為0x3900檢查編譯生成的bin文件,到0x3900處可以看到myTest1的內(nèi)容,在0x4000處可以看到myTest的內(nèi)容,(5)其它說(shuō)明:如果

5、在0x3000到0x3900的程序空間沒(méi)有內(nèi)容時(shí),把myTestCall的地址指針指到0x3800(在0x3000到0x3900之間)時(shí),會(huì)從0x3900處開(kāi)始執(zhí)行.至於在Load中調(diào)用AP中的函數(shù)的方法與此類似,但是相應(yīng)的參數(shù)傳遞可能要另尋方法.*keil C51絕對(duì)地址訪問(wèn)在利用keil進(jìn)行8051單片機(jī)編程的時(shí),常常需要進(jìn)行絕對(duì)地址進(jìn)行訪問(wèn).特別是對(duì)硬件操作,如DA AD采樣,LCD液晶操作,打印操作.等等.C51提供了三種訪問(wèn)絕對(duì)地址的方法:1.絕對(duì)宏:在程序中,用“include”即可使用其中定義的宏來(lái)訪問(wèn)絕對(duì)地址,包括:CBYTE、XBYTE、PWORD、DBYTE、CWORD、X

6、WORD、PBYTE、DWORD具體使用可看一看absacc.h便知例如:rval=CBYTE0x0002;指向程序存貯器的0002h地址rval=XWORD 0x0002;指向外RAM的0004h地址2. _at_關(guān)鍵字直接在數(shù)據(jù)定義后加上_at_ const即可,但是注意:(1)絕對(duì)變量不能被初使化;(2)bit型函數(shù)及變量不能用_at_指定。例如:idata struct link list _at_ 0x40;指定list結(jié)構(gòu)從40h開(kāi)始。xdata char text25b _at_0xE000;指定text數(shù)組從0E000H開(kāi)始提示:如果外部絕對(duì)變量是I/O端口等可自行變化數(shù)據(jù),需

7、要使用volatile關(guān)鍵字進(jìn)行描述,請(qǐng)參考absacc.h。3.連接定位控制此法是利用連接控制指令code xdata pdata data bdata對(duì)“段”地址進(jìn)行,如要指定某具體變量地址,則很有局限性,不作詳細(xì)討論。附:(c51)/*- ABSACC.H Direct access to 8051, extended 8051 and Philips 80C51MX memory areas. Copyright (c) 1988-2002 Keil Elektronik GmbH and Keil Software, Inc. All rights reserved. -*/ #if

8、ndef _ABSACC_H_ #define _ABSACC_H_ #define CBYTE (unsigned char volatile code *) 0) #define DBYTE (unsigned char volatile data *) 0) #define PBYTE (unsigned char volatile pdata *) 0) #define XBYTE (unsigned char volatile xdata *) 0) #define CWORD (unsigned int volatile code *) 0) #define DWORD (unsi

9、gned int volatile data *) 0) #define PWORD (unsigned int volatile pdata *) 0) #define XWORD (unsigned int volatile xdata *) 0) #ifdef _CX51_ #define FVAR(object, addr) (*(object volatile far *) (addr) #define FARRAY(object, base) (object volatile far *) (base) #define FCVAR(object, addr) (*(object c

10、onst far *) (addr) #define FCARRAY(object, base) (object const far *) (base) #else #define FVAR(object, addr) (*(object volatile far *) (addr)+0x10000L) #define FCVAR(object, addr) (*(object const far *) (addr)+0x810000L) #define FARRAY(object, base) (object volatile far *) (base)+0x10000L) #define

11、FCARRAY(object, base) (object const far *) (base)+0x810000L) #endif #endif 附:(c166) /*- ABSACC.H Direct access to 166 memory areas for C166/EC+ Version 5. Copyright (c) 1992-2004 Keil Elektronik GmbH and Keil Software, Inc. All rights reserved. -*/ #ifndef _ABSACC_H_ #define _ABSACC_H_ #if (_MODEL_

12、= 0) #define MVAR(object, addr) (*(object volatile *) (addr) #define MARRAY(object, base) (object volatile *) (base) #else #define MVAR(object, addr) (*(object volatile far *) (addr) #define MARRAY(object, base) (object volatile far *) (base) #define HVAR(object, addr) (*(object volatile huge *) (ad

13、dr) #define HARRAY(object, base) (object volatile huge *) (base) #define XVAR(object, addr) (*(object volatile xhuge *) (addr) #define XARRAY(object, base) (object volatile xhuge *) (base) #endif #endif以下來(lái)自轉(zhuǎn)載:使用KeilC51軟件,可以很方便地將代碼或者數(shù)據(jù)絕對(duì)定位到某個(gè)地址。1、代碼定位:方法1:使用偽指令CSEG。比如要將MyFunc1定位到代碼區(qū)C:0x1000,則新建一個(gè)A51文

14、件,添加以下內(nèi)容:PUBLIC MYFUNC1CSEG AT 1000HMYFUNC1:;其它代碼RET在其它源文件中,就可以調(diào)用MyFunc()函數(shù)了。需要注意的是,編譯器不檢測(cè)傳遞參數(shù)的數(shù)目,僅檢測(cè)函數(shù)是否有返回值。方法2:使用BL51 Locate選項(xiàng)。比如在main.c中定義了一個(gè)MyFunc2函數(shù),并且要將該函數(shù)定位到代碼區(qū)C:0x2000,則從菜單中選擇Project-Options for Target Target1,在彈出的對(duì)話框中選擇BL51 Locate頁(yè),在下面的code欄中寫上?PR?MYFUNC2?MAIN(0x2000)即可。如果想定位多個(gè)函數(shù),也可以使用*通配符

15、。2、變量定位:只有全局變量可以絕對(duì)定位,局部變量無(wú)法實(shí)現(xiàn)絕對(duì)定位。方法1:使用_at_關(guān)鍵字。聲明一個(gè)全局變量unsigned char data MyBuf18 _at_ 0x20;方法2:使用BL51 Locate選項(xiàng)。比如將main.c中定義的所有data型的全局變量定位到數(shù)據(jù)區(qū)D:0x28開(kāi)始的空間,則從菜單中選擇Project-Options for Target Target1,在彈出的對(duì)話框中選擇BL51 Locate頁(yè),在下面的data欄中寫上?DT?MAIN(0x28)即可。如果是idata,則使用?ID?MAIN(0x28),如果是xdata,則使用?XD?MAIN(0x

16、28),如果是pdata,則使用?PD?MAIN(0x28)3、堆棧定位:在STARTUP.A51文件中定義了堆棧區(qū)?STACK,其起始地址同樣可以在BL51 Locate頁(yè)中設(shè)置,在Stack欄寫上?STACK(0x80)BL51 locate選項(xiàng)卡中code range和xdata range如果不填寫,編譯默認(rèn)將程序中相應(yīng)代碼和變量從空間前面取起網(wǎng)上看到有人提到在keil中使用_at_進(jìn)行絕對(duì)地址定位問(wèn)題,我簡(jiǎn)單介紹一下它的用法。使用_at_關(guān)鍵字對(duì)存儲(chǔ)器進(jìn)行絕對(duì)地址定位程序如下i ncludechar xdata LED_Data50 _at_ 0x8000;main()LED_Dat

17、a0 = 0x23;在keil中運(yùn)行以上程序可以在存儲(chǔ)器窗口中輸入x:0x8000可以看到0x8000地址中的值為0x23.值得指出的幾點(diǎn)是1.在給變量LED_Data50定位絕對(duì)地址空間時(shí),不能對(duì)其賦初值。2.char xdata LED_Data50 _at_ 0x8000;這條語(yǔ)句不能主函數(shù)中。有些網(wǎng)友提到在按著keil說(shuō)明中用_at_進(jìn)行絕對(duì)地址定位時(shí),編譯會(huì)出現(xiàn)錯(cuò)誤274,就是將這條語(yǔ)句放在主函數(shù)中的原因。3.keil中地址是自動(dòng)分配的,所以除非特殊情況否則不提倡使用絕對(duì)地址定位。初學(xué)者因帖別注意。不要把c當(dāng)作匯編使用。對(duì)需要/RST復(fù)位后要保持變量不變,防止意外改變(比如升級(jí)到新程

18、序,變量地址可能被編譯器優(yōu)化到其他地方),比較有用!STARTUP.A51這個(gè)文件有什么用,有必要添加到工程嗎?如果不添加startup.a51文件,編譯器就會(huì)自動(dòng)加入一段初始化內(nèi)存以及堆棧等的代碼,這時(shí)的內(nèi)存初始化部分你就無(wú)法去控制了,當(dāng)然這在大部分情況下沒(méi)什么關(guān)系。但是如果你想你的程序在復(fù)位后,內(nèi)存里面的信息依然還保存著(所說(shuō)的“熱復(fù)位”),那么你就需要添加該啟動(dòng)文件,并且去里面修改內(nèi)存初始化部分,不要初始化你需要保留的部分內(nèi)存。請(qǐng)問(wèn)如何在keil編譯器里,編程時(shí)指定函數(shù)的絕對(duì)地址(無(wú)內(nèi)容)不好意思啊,我還從來(lái)沒(méi)有接觸過(guò)有這樣要求情況,不過(guò)從網(wǎng)上其他地方找了一篇你參考一下吧,、函數(shù)定位:假

19、如要把C源文件tools.c中的函數(shù)int BIN2HEX(int xx).放在CODE MEMORY的0x1000處,先編譯該工程,然后打開(kāi)該工程的M51文件,在* * * C O D E M E M O R Y * * *行下找出要定位的函數(shù)的名稱,應(yīng)該形如:CODE xxxxH xxxxH UNIT ?PR?_BCD2HEX?TOOLS然后在:Project-Options for Target .-BL51 Locate:Code中填寫如下內(nèi)容:?PR?_BCD2HEX?TOOLS(0x1000)再次Build,在M51中會(huì)發(fā)現(xiàn)該函數(shù)已放在CODE MEMORY的0x1000處了2、賦

20、初值的變量定位:要將某變量定位在一絕對(duì)位置且要賦初值,此時(shí)用_at_不能完成,則如下操作:在工程中建立一個(gè)新的文件,如InitVars.c,在其中對(duì)要處理的變量賦初值(假設(shè)是code變量):char code myVer = COPYRIGHT 2001-11;然后將該文件加入工程,編譯,打開(kāi)M51文件,若定義的是code型,則在* * * C O D E M E M O R Y * * *下可找到:CODE xxxxH xxxxH UNIT ?CO?INITVARS然后在:Project-Options for Target .-BL51 Locate:Code中填入:?CO?INITVAR

21、S(0x200)再次編譯即可。相應(yīng)地,如為xdata變量,則InitVars.c中寫:char xdata myVer = COPYRIGHT 2001-11;然后將該文件加入工程,編譯,打開(kāi)M51文件,在* * *X D A T A M E M O R Y* * *下可找到:XDATA xxxxH xxxxH UNIT ?XD?INITVARS然后在:Project-Options for Target .-BL51 Locate:Xdata中填入:?XD?INITVARS(0x200)再次編譯即可。相應(yīng)地,若定義的是data/idata等變量,則相應(yīng)處理即可。3、若有多個(gè)變量或函數(shù)要進(jìn)行絕

22、對(duì)地址定位,則應(yīng)按地址從低到高的順序排列。*PIC 51混編C18指定數(shù)據(jù)絕對(duì)地址51:RSEG是段選擇指令,要想明白它的意思就要了解段的意思。段是程序代碼或數(shù)據(jù)對(duì)象的存儲(chǔ)單位。程序代碼放到代碼段,數(shù)據(jù)對(duì)象放到數(shù)據(jù)段。段分兩種,一是絕對(duì)段,一是再定位段。絕對(duì)段在匯編語(yǔ)言中指定,在用L51聯(lián)接的時(shí)候,地址不會(huì)改變。用于如訪問(wèn)一個(gè)固定存儲(chǔ)器的i/o,或提供中斷向量的入口地址。而再定位段的地址是浮動(dòng)的。它的地址有L51對(duì)程序模塊連接時(shí)決定,C51對(duì)源程序編譯所產(chǎn)生的段都是再定位段,它都有段名和存儲(chǔ)類型。絕對(duì)段沒(méi)有段名。說(shuō)了這么多,大家可能還是不明白段是什么意思。別急,接著往下看。例如,你寫用C寫了一

23、個(gè)函數(shù)void test_fun(void) ,存在test.c中,用編譯器編譯以后. SRC FILE中看到:?PR?test_fun?TEST SEGMENT CODE /(函數(shù)放到代碼段中)寫這個(gè)函數(shù)體的時(shí)候: RSEG ?PR?test_fun?TEST /選擇已定位的代碼段為當(dāng)前段test_fun:/代碼所以函數(shù)的表達(dá)模式是這樣:?PR?函數(shù)名?文件名而函數(shù)名又分: 1:無(wú)參函數(shù)?PR?函數(shù)名?文件名2:有參函數(shù)?PR?_函數(shù)名?文件名3:再入函數(shù)?PR?_?函數(shù)名?文件名又例如你定義了全局變量unsigned char data temp1,temp2; unsigned char

24、 xdata temp3;在test.c文件中,編譯器會(huì)為每個(gè)文件分0到多個(gè)全局?jǐn)?shù)據(jù)段,相同類型的全局變量被存到同一段中。所以上面會(huì)編譯成如下:RSEG ? DT? TEST. temp1: DS 1. temp2: DS 1;RSEG ?XD? TEST. temp3: DS 1/下面是各個(gè)類型的數(shù)據(jù)全局段的表示?CO?文件名/常數(shù)段?XD? FILE_NAME /XDATA數(shù)據(jù)段?DT? FILE_NAME /DATA數(shù)據(jù)段?ID? FILE_NAME /IDATA.?BI? FILE_NAME / BIT .?BA? FILE_NAME /BDATA.?PD? FILE_NAME /PD

25、ATA.看到這里大家應(yīng)該明白段的意思了吧。也許你會(huì)問(wèn),這有什么作用哪?它就是用在當(dāng)你需要用匯編語(yǔ)言寫一部份程序的時(shí)候,把匯編寫的函數(shù)放在這個(gè)問(wèn)件中,改名xxx.a51,按上面的規(guī)則寫。編譯就好。既然知道了段的意思,現(xiàn)在我們回到SEG的用法上來(lái)。A51中有兩種段選擇指令:再定位段選擇指令和絕對(duì)段選擇指令.它們用來(lái)選擇當(dāng)前段是再定位段還是絕對(duì)段。使用不同的段選擇指令,將使程序定位在不同的地址空間之內(nèi)。1:再定位段的選擇指令是:RSEG段名它用來(lái)選擇一個(gè)在前面已經(jīng)定義過(guò)的再定位段作為當(dāng)前段。用法就像我們上面的例子,先申明了一個(gè)函數(shù)段,后面寫這個(gè)函數(shù)段。2:絕對(duì)段選擇指令CSEG AT絕對(duì)地址表達(dá)式

26、/絕對(duì)代碼段DSEG AT絕對(duì)地址表達(dá)式 /內(nèi)部絕對(duì)數(shù)據(jù)段XSEG AT絕對(duì)地址表達(dá)式 /外部絕對(duì)數(shù)據(jù)段ISEG AT絕對(duì)地址表達(dá)式 /內(nèi)部間接尋址絕對(duì)數(shù)據(jù)段BSEG AT絕對(duì)地址表達(dá)式 /絕對(duì)位尋址段它們的用法我舉一個(gè)例子:例如我們寫串口中斷程序,起始地址是0x23.就這樣寫CSEG AT 0X23LJMP serialISRRSEG ?PR?serialISR?TEST. serialISR:PIC:匯編函數(shù)使用同一個(gè)工程C文件中的變量,例如ICFLAG在C文件中定義,則匯編文件中定義方式為;定義外部變量EXTERN ICFLAG定義函數(shù)例如CARDATR:.RETGLOBAL CARDA

27、TR在同一個(gè)工程文件下調(diào)用匯編中的函數(shù)CARDATR則應(yīng)該定義函數(shù)extern void CARDATR(void);C18指定數(shù)據(jù)絕對(duì)地址例如:#pragma udata overlay RECBUFS =0x190 /200UINT8 NUMBER;UINT8 REC_BUF31;#pragma udata*8標(biāo)簽:KEILC51編程KEIL C51高級(jí)編程KEIL C51高級(jí)編程第一節(jié)絕對(duì)地址訪問(wèn)C51提供了三種訪問(wèn)絕對(duì)地址的方法:1.絕對(duì)宏:在程序中,用“include”即可使用其中定義的宏來(lái)訪問(wèn)絕對(duì)地址,包括:CBYTE、XBYTE、PWORD、DBYTE、CWORD、XWORD、P

28、BYTE、DWORD具體使用可看一看absacc.h便知例如:rval=CBYTE0x0002;指向程序存貯器的0002h地址rval=XWORD 0x0002;指向外RAM的0004h地址2. _at_關(guān)鍵字直接在數(shù)據(jù)定義后加上_at_ const即可,但是注意:(1)絕對(duì)變量不能被初使化;(2)bit型函數(shù)及變量不能用_at_指定。例如:idata struct link list _at_ 0x40;指定list結(jié)構(gòu)從40h開(kāi)始。xdata char text25b _at_0xE000;指定text數(shù)組從0E000H開(kāi)始提示:如果外部絕對(duì)變量是I/O端口等可自行變化數(shù)據(jù),需要使用vol

29、atile關(guān)鍵字進(jìn)行描述,請(qǐng)參考absacc.h。3.連接定位控制此法是利用連接控制指令code xdata pdata data bdata對(duì)“段”地址進(jìn)行,如要指定某具體變量地址,則很有局限性,不作詳細(xì)討論。第二節(jié)Keil C51與匯編的接口1.模塊內(nèi)接口方法是用pragma語(yǔ)句具體結(jié)構(gòu)是:#pragma asm匯編行#pragma endasm這種方法實(shí)質(zhì)是通過(guò)asm與ndasm告訴C51編譯器中間行不用編譯為匯編行,因而在編譯控制指令中有SRC以控制將這些不用編譯的行存入其中。2.模塊間接口C模塊與匯編模塊的接口較簡(jiǎn)單,分別用C51與A51對(duì)源文件進(jìn)行編譯,然后用L51將obj文件連接

30、即可,關(guān)鍵問(wèn)題在于C函數(shù)與匯編函數(shù)之間的參數(shù)傳遞問(wèn)題,C51中有兩種參數(shù)傳遞方法。(1)通過(guò)寄存器傳遞函數(shù)參數(shù)最多只能有3個(gè)參數(shù)通過(guò)寄存器傳遞,規(guī)律如下表:參數(shù)數(shù)目charintlong,float一般指針123R7R5R3R6 & R7R4 & R5R2 & R3R4R7R4R7R1R3R1R3R1R3(2)通過(guò)固定存儲(chǔ)區(qū)傳遞(fixed memory)這種方法將bit型參數(shù)傳給一個(gè)存儲(chǔ)段中:?function_name?BIT將其它類型參數(shù)均傳給下面的段:?function_name?BYTE,且按照預(yù)選順序存放。至于這個(gè)固定存儲(chǔ)區(qū)本身在何處,則由存儲(chǔ)模式默認(rèn)。(3)函數(shù)的返回值函數(shù)返回值

31、一律放于寄存器中,有如下規(guī)律:return typeRegistev說(shuō)明bit標(biāo)志位由具體標(biāo)志位返回char/unsigned char 1_byte指針R7單字節(jié)由R7返回int/unsigned int 2_byte指針R6 & R7雙字節(jié)由R6和R7返回,MSB在R6long&unsigned longR4R7MSB在R4, LSB在R7floatR4R732Bit IEEE格式一般指針R1R3存儲(chǔ)類型在R3高位R2低R1(4) SRC控制該控制指令將C文件編譯生成匯編文件(.SRC),該匯編文件可改名后,生成匯編.ASM文件,再用A51進(jìn)行編譯。第三節(jié)Keil C51軟件包中的通用文件

32、在C51LiB目錄下有幾個(gè)C源文件,這幾個(gè)C源文件有非常重要的作用,對(duì)它們稍事修改,就可以用在自己的專用系統(tǒng)中。1.動(dòng)態(tài)內(nèi)存分配init_mem.C:此文件是初始化動(dòng)態(tài)內(nèi)存區(qū)的程序源代碼。它可以指定動(dòng)態(tài)內(nèi)存的位置及大小,只有使用了init_mem( )才可以調(diào)回其它函數(shù),諸如malloc calloc,realloc等。calloc.c:此文件是給數(shù)組分配內(nèi)存的源代碼,它可以指定單位數(shù)據(jù)類型及該單元數(shù)目。malloc.c:此文件是malloc的源代碼,分配一段固定大小的內(nèi)存。realloc.c:此文件是realloc.c源代碼,其功能是調(diào)整當(dāng)前分配動(dòng)態(tài)內(nèi)存的大小。2. C51啟動(dòng)文件START

33、UP.A51啟動(dòng)文件STARTUP.A51中包含目標(biāo)板啟動(dòng)代碼,可在每個(gè)project中加入這個(gè)文件,只要復(fù)位,則該文件立即執(zhí)行,其功能包括:l定義內(nèi)部RAM大小、外部RAM大小、可重入堆棧位置l清除內(nèi)部、外部或者以此頁(yè)為單元的外部存儲(chǔ)器l按存儲(chǔ)模式初使化重入堆棧及堆棧指針l初始化8051硬件堆棧指針l向main( )函數(shù)交權(quán)開(kāi)發(fā)人員可修改以下數(shù)據(jù)從而對(duì)系統(tǒng)初始化常數(shù)名意義IDATALEN待清內(nèi)部RAM長(zhǎng)度XDATA START指定待清外部RAM起始地址XDATALEN待清外部RAM長(zhǎng)度IBPSTACK是否小模式重入堆棧指針需初始化標(biāo)志,1為需要。缺省為0IBPSTACKTOP指定小模式重入堆

34、棧頂部地址XBPSTACK是否大模式重入堆棧指針需初始化標(biāo)志,缺省為0XBPSTACKTOP指定大模式重入堆棧頂部地址PBPSTACK是否Compact重入堆棧指針,需初始化標(biāo)志,缺省為0PBPSTACKTOP指定Compact模式重入堆棧頂部地址PPAGEENABLE P2初始化允許開(kāi)關(guān)PPAGE指定P2值PDATASTART待清外部RAM頁(yè)首址PDATALEN待清外部RAM頁(yè)長(zhǎng)度提示:如果要初始化P2作為緊湊模式高端地址,必須:PPAGEENAGLE1,PPAGE為P2值,例如指定某頁(yè)1000H10FFH,則PPAGE10H,而且連接時(shí)必須如下:L51PDATA(1080H),其中1080

35、H是1000H10FFH中的任一個(gè)值。以下是STARTUP.A51代碼片斷,紅色是經(jīng)??赡苄枰薷牡牡胤剑?-; This file is part of the C51 Compiler package; Copyright KEIL ELEKTRONIK GmbH 1990;-; STARTUP.A51: This code is executed after processor reset.; To translate this file use A51 with the following invocation:; A51 STARTUP.A51; To link the modifi

36、ed STARTUP.OBJ file to your application use the following; L51 invocation:; L51 , STARTUP.OBJ;-; User-defined Power-On Initialization of Memory; With the following EQU statements the initialization of memory; at processor reset can be defined:; ; the absolute start-address of IDATA memory is always

37、0IDATALEN EQU 80H ; the length of IDATA memory in bytes.;XDATASTART EQU 0H ; the absolute start-address of XDATA memoryXDATALEN EQU 0H ; the length of XDATA memory in bytes.;PDATASTART EQU 0H ; the absolute start-address of PDATA memoryPDATALEN EQU 0H ; the length of PDATA memory in bytes.; Notes: T

38、he IDATA space overlaps physically the DATA and BIT areas of the; 8051 CPU. At minimum the memory space occupied from the C51; run-time routines must be set to zero.;-; Reentrant Stack Initilization; The following EQU statements define the stack pointer for reentrant; functions and initialized it:;

39、Stack Space for reentrant functions in the SMALL model.IBPSTACK EQU 0 ; set to 1 if small reentrant is used.IBPSTACKTOP EQU 0FFH+1 ; set top of stack to highest location+1.; Stack Space for reentrant functions in the LARGE model.XBPSTACK EQU 0 ; set to 1 if large reentrant is used.XBPSTACKTOP EQU 0F

40、FFFH+1; set top of stack to highest location+1.; Stack Space for reentrant functions in the COMPACT model.PBPSTACK EQU 0 ; set to 1 if compact reentrant is used.PBPSTACKTOP EQU 0FFFFH+1; set top of stack to highest location+1.;-; Page Definition for Using the Compact Model with 64 KByte xdata RAM; T

41、he following EQU statements define the xdata page used for pdata; variables. The EQU PPAGE must conform with the PPAGE control used; in the linker invocation.;PPAGEENABLE EQU 0 ; set to 1 if pdata object are used.PPAGE EQU 0 ; define PPAGE number.;-3.標(biāo)準(zhǔn)輸入輸出文件putchar.cputchar.c是一個(gè)低級(jí)字符輸出子程,開(kāi)發(fā)人員可修改后應(yīng)用到

42、自己的硬件系統(tǒng)上,例如向CLD或LEN輸出字符。缺?。簆utchar.c是向串口輸出一個(gè)字符XON|XOFF是流控標(biāo)志,換行符“*n”自動(dòng)轉(zhuǎn)化為回車/換行“rn”。getkey.cgetkey函數(shù)是一個(gè)低級(jí)字符輸入子程,該程序可用到自己硬件系統(tǒng),如矩陣鍵盤輸入中,缺省時(shí)通過(guò)串口輸入字符。4.其它文件還包括對(duì)Watch-Dog有獨(dú)特功能的INIT.A51函數(shù)以及對(duì)8C751適用的函數(shù),可參考源代碼。第四節(jié)段名協(xié)定與程序優(yōu)化1.段名協(xié)定(Segment Naming Conventions)C51編譯器生成的目標(biāo)文件存放于許多段中,這些段是代碼空間或數(shù)據(jù)空間的一些單元,一個(gè)段可以是可重定位的,也可

43、以是絕對(duì)段,每一個(gè)可重定位的段都有一個(gè)類型和名字,C51段名有以下規(guī)定:每個(gè)段名包括前綴與模塊名兩部分,前綴表示存儲(chǔ)類型,模塊名則是被編譯的模塊的名字,例如:?CO?main1:表示main1模塊中的代碼段中的常數(shù)部分?PR?function1?module表module模塊中函數(shù)function1的可執(zhí)行段,具體規(guī)定參閱手冊(cè)。2.程序優(yōu)化C51編譯器是一個(gè)具有優(yōu)化功能的編譯器,它共提供六級(jí)優(yōu)化功能。確保生成目標(biāo)代碼的最高效率(代碼最少,運(yùn)行速度最快)。具體六級(jí)優(yōu)化的內(nèi)容可參考幫助。在C51中提供以下編譯控制指令控制代碼優(yōu)化:OPTIMIZE(SJXE):盡量采用子程序,使程序代碼減少。NOA

44、REGS:不使用絕對(duì)寄存器訪問(wèn),程序代碼與寄存器段獨(dú)立。NOREGPARMS:參數(shù)傳遞總是在局部數(shù)據(jù)段實(shí)現(xiàn),程序代碼與低版本C51兼容。OPTIMIZE(SIZE)AK OPTIMIZE(speed)提供6級(jí)優(yōu)化功能,缺省為:OPTIMIZE(6,SPEED)。第五節(jié)KeilC51的代碼效率一、存儲(chǔ)模式的影響存儲(chǔ)模式?jīng)Q定了缺省變量的存儲(chǔ)空間,而訪問(wèn)各空間變量的匯編代碼的繁簡(jiǎn)程度決定了代碼率的高低。例如:一個(gè)整形變量i,如放于內(nèi)存18H、19H空間,則+i的操作編譯成四條語(yǔ)句:INC 0x19MOV A,0x19JNZ 0x272DINC 0x180x272D:而如果放于外存空間0000H、00

45、01H則+i的操作編譯成九條語(yǔ)句:MOV DPTR,0001MOVX A, DPTRINC AMOVX DPTR,AJNz #5MOV OPTR,#0000MOVX A,DPTRINC AMOVX DPTR,A就匯編之后的語(yǔ)句而言,對(duì)外部存儲(chǔ)器的操作較內(nèi)部存儲(chǔ)器操作代碼率要低得多,生成的語(yǔ)句為內(nèi)存的兩倍以上,而程序中有大量的這種操作,可見(jiàn)存儲(chǔ)模式對(duì)代碼率的響了。因此程序設(shè)計(jì)的原則是1、存儲(chǔ)模式從small-Compact-large依次選擇,實(shí)在是變量太多,才選large模式。2、即使選擇了large模式,對(duì)一些常用的局部的或者可放于內(nèi)存中的變量,最好放于內(nèi)存中,以盡量提高程序的代碼率。二、程

46、序結(jié)構(gòu)的影響程序的結(jié)構(gòu)單元包括模塊、函數(shù)等等。同樣的功能,如果結(jié)構(gòu)越復(fù)雜,其所涉及的操作、變量、功能模塊函數(shù)等就越多,較之結(jié)構(gòu)性好,代碼簡(jiǎn)單的程序其代碼率自然就低得多。此外程序的運(yùn)行控制語(yǔ)句,也是影響代碼率的關(guān)鍵因素,例如:switch -case語(yǔ)句,許多編譯器都把它們譯得非常復(fù)雜,Keil C51也不例外,相對(duì)較為簡(jiǎn)易的Switch-case語(yǔ)句,編譯成跳轉(zhuǎn)指令形式,代碼率較高,但對(duì)較為復(fù)雜的Switch-Case,則要調(diào)用一個(gè)系統(tǒng)庫(kù)函數(shù)?C?ICASE進(jìn)行處理,非常復(fù)雜。再如if( ),while( ),等語(yǔ)句也是代碼相對(duì)較低的語(yǔ)句,但編譯以后比switch-case要高得多。因此建議設(shè)

47、計(jì)者盡量少用switch-case之類語(yǔ)句來(lái)控制程序結(jié)構(gòu),以提高代碼率。除以上兩點(diǎn)外,其它因素也會(huì)對(duì)代碼率產(chǎn)生影響,例如:是否用寄存器傳遞參數(shù)即NOAREGS選項(xiàng)是否有是否包括調(diào)試信息:即DEBUG選項(xiàng)是否包括擴(kuò)展的調(diào)試信息:即BJECTEXTEND第六節(jié)如何優(yōu)化C語(yǔ)言代碼(程序員必讀)1、選擇合適的算法和數(shù)據(jù)結(jié)構(gòu)應(yīng)該熟悉算法語(yǔ)言,知道各種算法的優(yōu)缺點(diǎn),具體資料請(qǐng)參見(jiàn)相應(yīng)的參考資料,有很多計(jì)算機(jī)書籍上都有介紹。將比較慢的順序查找法用較快的二分查找或亂序查找法代替,插入排序或冒泡排序法用快速排序、合并排序或根排序代替,都可以大大提高程序執(zhí)行的效率。.選擇一種合適的數(shù)據(jù)結(jié)構(gòu)也很重要,比如你在一堆隨機(jī)存放的數(shù)中使用了大量的插入和刪除指令,那使用鏈表要快得多。數(shù)組與指針語(yǔ)句具有十分密碼的關(guān)系,一般來(lái)說(shuō),指針比較靈活簡(jiǎn)潔,而數(shù)組則比較直觀,容易理解。對(duì)于大部分的編譯器,使用指針比使用數(shù)組生成的代碼更短,執(zhí)行效率更高。但是在Keil中則相反,

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論