版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
第6章TMS320C64xDSP的C/C++程序設(shè)計6.1C/C++程序設(shè)計基礎(chǔ)6.2程序設(shè)計示例6.3用C語言和匯編語言混合編程6.1C/C++程序設(shè)計基礎(chǔ)DSP生產(chǎn)廠商及第三方為DSP軟件開發(fā)提供了C編譯器,使得利用高級語言實(shí)現(xiàn)DSP程序的開發(fā)成為可能。在TI公司的DSP軟件開發(fā)平臺CCS中,又提供了優(yōu)化的C編譯器,可以對C語言程序進(jìn)行優(yōu)化編譯,提高程序效率,目前在某些應(yīng)用中,C語言優(yōu)化編譯的結(jié)果可以達(dá)到手工編寫的匯編語言效率的90%以上。DSP生產(chǎn)廠商和相關(guān)公司也在不斷對C優(yōu)化編譯器進(jìn)行改進(jìn)設(shè)計,C語言程序優(yōu)化編譯的效果將會進(jìn)一步改善。返回首頁6.1.1面向DSP的程序設(shè)計原則面向DSP的C/C++程序設(shè)計和通用計算機(jī)上的C/C++程序設(shè)計從本質(zhì)和工作原理上來說是一致的,但受硬件資源和處理對象的不同,存在一些區(qū)別:DSP的數(shù)據(jù)存儲區(qū)有限,所以只能實(shí)時處理小批量數(shù)據(jù);DSP代碼需要絕對定位,計算機(jī)的C代碼由操作系統(tǒng)定位。DSP的C/C++程序設(shè)計原則:
靈活使用嵌入式C語言中的位操作指令;
編譯系統(tǒng)不允許有太多的程序嵌套;
需要考慮對DSP硬件的時序要求;
區(qū)別不同庫函數(shù)的使用;
不同存儲類型變量的使用;
盡可能模塊化設(shè)計。類型大小數(shù)據(jù)格式最小值最大值Signedchar16位ASCII-3276832767char,unsignedchar16位ASCII065535short,signedshort16位二進(jìn)制補(bǔ)碼-3276832767unsignedshort16位二進(jìn)制065535int,signedint16位二進(jìn)制補(bǔ)碼-3276832767unsignedint16位二進(jìn)制065535long,signedlong32位二進(jìn)制補(bǔ)碼-21474836482147483647unsignedlong32位二進(jìn)制04294967295enum16位二進(jìn)制補(bǔ)碼-3276832767float32位IEEE32位1.175494e-383.40282346e+38double32位IEEE32位1.175494e-383.40282346e+38longdouble32位IEEE32位1.175494e-383.40282346e+38pointers16位二進(jìn)制00x0FFFF表6.1CCS中C語言數(shù)據(jù)類型6.1.2C/C++語言數(shù)據(jù)類型6.1.5C/C++的DSP訪問規(guī)則1.DSP片內(nèi)寄存器的訪問CCS工程中的頭文件與其它基于C語言的開發(fā)環(huán)境中的頭文件基本相同,主要是用來定義工程中的常量和數(shù)據(jù)結(jié)構(gòu)。為了提高開發(fā)效率,開發(fā)人員往往會將DSP片內(nèi)的控制寄存器定義寫成一個頭文件(如reg.h),這樣在各個基于相同型號DSP的開發(fā)中,可以共享這個定義控制寄存器的頭文件。在C語言中對DSP片內(nèi)寄存器一般采用指針方式來訪問,所以常常采用的方法是將DSP寄存器地址的列表定義在頭文件,中如下所示:#defineIMR(volatileunsignedint*)0x0000#defineIFR(volatileunsignedint*)0x0001#defineST0(volatileunsignedint*)0x0006#defineST1(volatileunsignedint*)0x0007#defineAL(volatileunsignedint*)0x0008#defineAH(volatileunsignedint*)0x0009#defineAG(volatileunsignedint*)0x000A#defineBL(volatileunsignedint*)0x000B#defineBH(volatileunsignedint*)0x000C#defineBG(volatileunsignedint*)0x000D#defineT(volatileunsignedint*)0x000E#defineTRN(volatileunsignedint*)0x000F#defineAR0(volatileunsignedint*)0x0010#defineAR1(volatileunsignedint*)0x0011#defineAR2(volatileunsignedint*)0x0012#defineSP(volatileunsignedint*)0x0018#defineBK(volatileunsignedint*)0x0019#defineBRC(volatileunsignedint*)0x0001A#defineRSA(volatileunsignedint*)0x001B#defineREA(volatileunsignedint*)0x001C#definePMST(volatileunsignedint*)0x001D#defineXPC(volatileunsignedint*)0x001E在用戶程序中,若要讀出或者寫入一個特定的寄存器,就要對相應(yīng)的指針進(jìn)行操作。下例通過指針操作對ST0和AR1進(jìn)行初始化Intuserfunc(){…*ST0=0x1278;*AR1=0x6013;…}2.DSP內(nèi)部和外部存儲器的訪問規(guī)則
DSP對存儲器的訪問也采用指針方式。例:對內(nèi)部存儲器單元0x4000和外部存儲器單元0x80FF進(jìn)行操作。
int*data1=0x4000;int*data2=0x80FF;intuserfunc(){…*data1=7000;*data2=0;…}3.DSPI/O端口的訪問規(guī)則在C語言中讀寫DSP的I/O端口空間,用關(guān)鍵字ioport實(shí)現(xiàn)。用關(guān)鍵字ioport定義I/O端口的格式如下:
ioporttypeporthex_num其中ioport是關(guān)鍵字,指出這是一個I/O端口變量。type只能是char、short、int或unsigned這幾種數(shù)據(jù)類型。porthex_num是端口號,hex_num是一個十六進(jìn)制數(shù)。所有端口變量都必須在文件級定義,不能在函數(shù)中定義。下面的代碼定義I/O端口為unsignedport10h,將數(shù)據(jù)a寫入port10h,然后從port10h讀入數(shù)據(jù)存到b中:Ioportunsignedport10;/*端口說明*/intfunc(){…port10=a;/*數(shù)據(jù)a寫入port10h*/…b=port10;/*從port10h讀出數(shù)據(jù)存到b*/}端口變量不僅可在分配端口中使用,也可像其他變量一樣使用a=port10+b/*從port10h讀入數(shù)據(jù)并加上數(shù)據(jù)b,再存到a中*/port10+=a/*從port10h讀出數(shù)據(jù)并加上數(shù)據(jù)a,將結(jié)果從port10h輸出*/在函數(shù)調(diào)用時,I/O端口變量的數(shù)值可以傳遞,但I(xiàn)/O端口變量本身不能當(dāng)作函數(shù)參數(shù)。例:call(port10);/*從port10h讀出數(shù)據(jù),將該數(shù)據(jù)作為參數(shù)并調(diào)用相應(yīng)子函數(shù)*/call(&port10);/*無效的參數(shù)傳遞*/6.3C語言和匯編語言混合編程6.3.1獨(dú)立的C模塊和匯編模塊接口6.3.2從C程序中訪問匯編程序變量6.3.3在C程序中直接嵌入?yún)R編語句
返回首頁用C語言和匯編語言混合編程,能充分利用DSP芯片的資源,更好地發(fā)揮C語言和匯編語言進(jìn)行軟件開發(fā)的各自的優(yōu)點(diǎn),可以將兩者有機(jī)結(jié)合起來,兼顧兩者的優(yōu)點(diǎn),避免其弊端。因此,在很多情況下,采用混合編程方法能更好地達(dá)到設(shè)計要求,完成設(shè)計功能。C語言和匯編語言的混合編程有以下幾種方法:
(1)獨(dú)立編寫匯編程序和C程序,分開編譯或匯編形成各自的目標(biāo)代碼模塊,用鏈接器將C模塊和匯編模塊鏈接起來,這是一種靈活性較大的方法。
(2)在C程序中直接內(nèi)嵌匯編語句
(3)將C程序編譯生成相應(yīng)的匯編程序,手工修改和優(yōu)化C編譯器生成的匯編代碼。
獨(dú)立編寫匯編程序和C程序,分開編譯或匯編形成各自的目標(biāo)代碼模塊,用鏈接器將C模塊和匯編模塊鏈接起來,這是一種靈活性較大的方法。
采用這種方法,C程序可以調(diào)用匯編程序,并且可以訪問匯編程序中定義的變量。同樣,匯編程序也可以調(diào)用C程序或訪問C程序中定義的變量。但用戶必須自己維護(hù)各匯編模塊的入口和出口代碼,自己計算傳遞的參數(shù)在堆棧中的偏移量,工作量稍大,但能做到對程序的絕對控制。在編寫C程序和匯編程序時,必須遵循有關(guān)的寄存器規(guī)則和函數(shù)調(diào)用規(guī)則。6.3.1獨(dú)立的C模塊和匯編模塊接口寄存器規(guī)則明確了編譯器如何使用寄存器以及在函數(shù)調(diào)用過程中如何保護(hù)寄存器。如果匯編程序不符合寄存器使用規(guī)則,則C運(yùn)行環(huán)境將會被破壞。(1)輔助寄存器:AR1、AR6、AR7由被調(diào)用函數(shù)保護(hù);AR0、AR2、AR3、AR4、AR5由調(diào)用函數(shù)保護(hù),在被調(diào)用函數(shù)中可以自由使用且不必恢復(fù)。(2)堆棧指針SP在函數(shù)調(diào)用時必須保護(hù),但它是自動保護(hù)的。(3)ARP
在函數(shù)進(jìn)入和返回時,必須為0,即當(dāng)前輔助寄存器為AR0。函數(shù)執(zhí)行時可以為其他值。1.TMS320C54xDSP中寄存器規(guī)則(4)在默認(rèn)的情況下,編譯器總是認(rèn)為ST1中的OVM為0。因此,若在匯編程序中將OVM置為1,則返回C/C++環(huán)境時,必須將其恢復(fù)為0。(5)在默認(rèn)的情況下,編譯器總是認(rèn)為CPL為1。因此,若在匯編程序中將CPL清0,則在返回C/C++環(huán)境時,必須將其恢復(fù)為1。(6)寄存器變量編譯器為兩個寄存器關(guān)鍵字聲明的變量分配寄存器,第一個變量必須聲明為AR1,第二個變量必須聲明為AR6,其順序不能改變。變量必須聲明為全局變量,必須在變量列表和函數(shù)語句的第一塊中聲明。其他狀態(tài)位和寄存器在子程序中可以任意使用,不必將其恢復(fù)。寄存器使用和保護(hù)規(guī)則寄存器用途由被調(diào)用函數(shù)保護(hù)由調(diào)用函數(shù)保護(hù)AR0指針和表達(dá)式不是是AR1指針和表達(dá)式是不是AR2~AR5指針和表達(dá)式不是是AR6指針和表達(dá)式是不是AR7指針、表達(dá)式和結(jié)構(gòu)指針是不是A表達(dá)式,傳遞第一個參數(shù)給函數(shù),返回函數(shù)值不是是B表達(dá)式不是是SP堆棧指針不是是T乘法和移位表達(dá)式不是是ST0,ST1狀態(tài)寄存器見表2見表2BRC塊重復(fù)寄存器不是是表2狀態(tài)寄存器字段描述字段字段名稱狀態(tài)位值修改ARP輔助寄存器指針0可以ASM累加器移位——可以BRAF塊循環(huán)標(biāo)志——不可以C進(jìn)位標(biāo)志——可以C16雙16位標(biāo)志0不可以CMPT兼容方式選擇0不可以CPL編譯方式選擇1不可以FRCT小數(shù)方式選擇0不可以O(shè)VA累加器A溢出標(biāo)志——可以O(shè)VB累加器B溢出標(biāo)志——可以O(shè)VM溢出方式位選擇0只能在內(nèi)部修改SXM符號擴(kuò)展方式選擇——可以SMUL飽和方式選擇0只能在內(nèi)部修改SST飽和方式存儲0不可以TC測試位標(biāo)準(zhǔn)——可以函數(shù)調(diào)用涉及參數(shù)傳遞、內(nèi)存使用等問題。C編譯器規(guī)定了一組嚴(yán)格的函數(shù)調(diào)用規(guī)則。除特殊的運(yùn)行支持函數(shù)外,任何調(diào)用C函數(shù)或被C函數(shù)調(diào)用的函數(shù)都必須遵循規(guī)則,否則會破壞C運(yùn)行環(huán)境而導(dǎo)致程序失敗。2.TMS320C54xDSP中函數(shù)調(diào)用規(guī)則(1)參數(shù)傳遞
函數(shù)調(diào)用前,將參數(shù)以逆序壓入運(yùn)行堆棧,即最右邊的參數(shù)最先入棧,然后自右向左將參數(shù)依次入棧。但是,對于TMS320C54X,在函數(shù)調(diào)用時,第一個參數(shù)放入累加器A中進(jìn)行傳遞。若參數(shù)是長整型和浮點(diǎn)數(shù)時,則低位字先壓棧,高位字后壓棧。若參數(shù)中有結(jié)構(gòu)形式,則調(diào)用函數(shù)給結(jié)構(gòu)分配空間,其地址通過累加器A傳遞給被調(diào)用函數(shù)。函數(shù)調(diào)用時堆棧的使用如下所示:
函數(shù)調(diào)用規(guī)則包括:返回地址PC函數(shù)參數(shù)2函數(shù)參數(shù)3SPSP+1SP+2堆棧函數(shù)參數(shù)1累加器A高地址低地址(2)局部幀的產(chǎn)生每調(diào)用一個函數(shù),就建立一個當(dāng)前函數(shù)幀。C環(huán)境利用該幀保護(hù)調(diào)用者的有關(guān)信息、傳遞參數(shù)和生成局部變量塊。在C語言中調(diào)用匯編語言編寫的子程序,主要應(yīng)弄清楚堆棧的使用情況,特別注意這里使用的堆棧不是DSP的硬件堆棧,而是.cmd文件定義的軟堆棧。TMS320C54x中調(diào)用函數(shù)時堆棧的使用情況(3)函數(shù)的返回
如果被調(diào)用函數(shù)修改了寄存器AR1,AR6和AR7,則必須予以恢復(fù)。函數(shù)的返回值保存在累加器A中。整數(shù)和指針在累加器A的低16位中返回;浮點(diǎn)數(shù)和長整型數(shù)在累加器A的32位中返回;如果函數(shù)返回一個結(jié)構(gòu)體,則被調(diào)用函數(shù)將結(jié)構(gòu)體的內(nèi)容拷貝到累加器A所指向的存儲器空間;如果函數(shù)沒有返回值,則A置0。(1)函數(shù)如何調(diào)用函數(shù)(調(diào)用者)在調(diào)用被調(diào)用函數(shù)時執(zhí)行以下任務(wù):①調(diào)用者將第一個(最左邊)的參數(shù)值放進(jìn)累加器A。調(diào)用者將剩下的參數(shù)按自右向左的順序傳進(jìn)參數(shù)塊,剩下的最左邊的參數(shù)在最低的地址。②若函數(shù)返回一個結(jié)構(gòu),則調(diào)用者為該結(jié)構(gòu)分配空間,然后用累加器A傳遞返回空間的地址給被調(diào)用的函數(shù)。③調(diào)用者調(diào)用函數(shù)。(2)被調(diào)用函數(shù)如何響應(yīng)被調(diào)用函數(shù)執(zhí)行以下任務(wù):注意:如果被調(diào)用函數(shù)是C/C++函數(shù),則下面步驟都是由匯編器自動完成。如果被調(diào)用函數(shù)是匯編函數(shù),則:①若被調(diào)用函數(shù)要修改AR1,AR6或AR7,則首先將他們壓入堆棧。②被調(diào)用函數(shù)通過從SP減去一個常數(shù),為自身局部變量塊和局部參數(shù)塊分配存儲器。該常數(shù)按以下公式計算,即:
局部變量塊的大?。植繀?shù)塊的大小+paddingpadding值是為了保證SP對準(zhǔn)偶數(shù)邊界而可能要求補(bǔ)充的一個字,padding為1或0。之所以SP要對準(zhǔn)偶數(shù)邊界,是因?yàn)?000系列DSP指令可一次讀寫存儲器的32b,例如DLD,DADD等。這樣,編譯器必須保證所有32b的目標(biāo)都駐留在偶數(shù)邊界。對于混合編程而言可以在匯編函數(shù)中,按本步驟的方法在堆棧中分配局部幀,但本方法相對比較麻煩,尤其該匯編函數(shù)還要調(diào)用其他函數(shù)時,所以,一般而言編程者通常用其他方法分配局部幀,比如用.bss偽指令定義局部變量供函數(shù)使用。③被調(diào)用函數(shù)執(zhí)行函數(shù)中的應(yīng)用代碼。④若被調(diào)用函數(shù)返回一個值,則被調(diào)用函數(shù)將該值放在累加器A中;若被調(diào)用函數(shù)返回一個結(jié)構(gòu),則被調(diào)用函數(shù)將該結(jié)構(gòu)復(fù)制到累加器A指到的存儲器塊;若調(diào)用者不返回函數(shù)值,則A被置0。⑤被調(diào)用函數(shù)給SP上加上第二步計算的常數(shù),釋放為局部變量和局部參數(shù)分配的存儲空間。對混合編程而言,如果編程者沒有在堆棧中分配局部幀,則本步驟省略。⑥被調(diào)用函數(shù)恢復(fù)所有保存的寄存器。⑦被調(diào)用函數(shù)執(zhí)行返回。匯編語言被調(diào)用函數(shù)的例子:callee:;函數(shù)入口PSHMAR6;存AR6PSHMAR7;存AR7FRAME#-15;分配函數(shù)體框架參數(shù)
┋
;函數(shù)體FRAME#15;分配函數(shù)體框架參數(shù)POPMAR7;恢復(fù)AR7POPMAR6;恢復(fù)AR6RET;返回在編寫?yīng)毩⒌膮R編程序時,必須注意以下幾點(diǎn):(1)不論是用C語言編寫的函數(shù)還是用匯編語言編寫的函數(shù),都必須遵循寄存器使用規(guī)則。(2)必須保護(hù)函數(shù)要用到的幾個特定寄存器。
(3)中斷程序必須保護(hù)所有用到的寄存器。(4)從匯編程序調(diào)用C函數(shù)時,第一個參數(shù)(最左邊)必須放入累加器A中,剩下的參數(shù)按自右向左的順序壓入堆棧??偨Y(jié)(5)調(diào)用C函數(shù)時,注意C函數(shù)只保護(hù)了幾個特定的寄存器,而其他是可以自由使用的。(6)長整型和浮點(diǎn)數(shù)在存儲器中存放的順序是低位字在高地址,高位字在低地址。(7)如果函數(shù)有返回值,返回值存放在累加器A中。(8)匯編語言模塊不能改變由C模塊產(chǎn)生的.cinit段,如果改變其內(nèi)容將會引起不可預(yù)測的后果。(9)編譯器在所有標(biāo)識符(函數(shù)名、變量名等)前加下劃線“_”。
(10)任何在匯編程序中定義的對象或函數(shù),如果需要在C程序中訪問或調(diào)用,則必須用匯編指令.global定義。
(11)編輯模式CPL指示采用何種指針尋址,如果CPL=1,則采用堆棧指針SP尋址;如果CPL=0,則選擇頁指針DP進(jìn)行尋址。
[例1]在C語言中調(diào)用匯編語言函數(shù)C程序:
Extern
int
asmfunc
(
);
/*聲明外部的匯編子程序*/
/*注意函數(shù)名前不要加下劃線*/
int
gvar;
/*定義全局變量*/
main(
)
{
int
i=3;
gvar=asmfunc(i);
/*進(jìn)行函數(shù)調(diào)用*/
}匯編程序:
_asmfunc:
;函數(shù)名前一定要有下劃線
ADD
*(_gvar),A
;加法結(jié)果存在A中
STL
A,*(_gvar)
;將A中的結(jié)果存到gvar
RETD
;子程序返回返回本節(jié)[例2]用C/C++編寫的主程序調(diào)用匯編語言編寫的32位乘法運(yùn)算子程序。雖然用C/C++語言表達(dá)32b乘法運(yùn)算較為方便和明了,但由于C/C++語言無法很好利用DSP匯編語言為實(shí)現(xiàn)各種乘法運(yùn)算而提供的指令,而使得C/C++程序效率低下。所以這里用匯編語言完成32b乘法運(yùn)算,再用C/C++程序調(diào)用它。算法簡介由于16b定點(diǎn)DSP中沒有32b乘法指令,所以一定要用幾種16b乘法指令結(jié)合一定算法來進(jìn)行32b乘法運(yùn)算。一個32b數(shù)在存儲器中是分開存儲的。高16位存放在低地址,它在進(jìn)行乘法運(yùn)算是可以看作一個16b有符號數(shù);低16位存放在相鄰的低地址,他進(jìn)行乘法運(yùn)算時可以看作一個16b無符號數(shù)。于是算式如下:x1
x0
y1
y0
×x0×y0
x1×y0
y1×x0
y1×x1
w0
w1
w2
w3
U×U
S×U
S×U
S×S
U
U
U
S
其中:S代表符號數(shù);U代表無符號數(shù)。由上算式可見,在32b乘法運(yùn)算中,實(shí)際上包含了3種乘法運(yùn)算:U*U,S*U和S*S。一般的乘法運(yùn)算指令都是兩個帶符號數(shù)相乘,即S*S。所以在編程時,還要用到以下兩條乘法指令:#include<stdio.h>#include<stdlib.h>intmain(){externint*MPY32(longX32,longY32);聲明外部的32b乘法運(yùn)算匯編子程序,該函數(shù)返回指針值intw[4]int*pintip=MPY32(0x11112222,0x33334444);進(jìn)行函數(shù)調(diào)用;該指針指向數(shù)據(jù)存儲器中,存放相乘結(jié)果單元的首地址for(i=0;i<4;i++){w[i]=*p++;將乘法結(jié)果存到數(shù)組中printf(“%x\n”,W[i]);以十六進(jìn)制方式輸出該數(shù)組值}}舉例:C語言主程序在主程序中進(jìn)行MPY32函數(shù)調(diào)用時,函數(shù)傳遞情形如圖2所示。函數(shù)MPY32的第一參數(shù)存放在A累加器中,第二個參數(shù)在堆棧中,高16位在堆棧中的低地址,低16位在堆棧中的高地址。由于MPY32是匯編語言函數(shù),所以編譯器不為其分配局部幀,局部幀的分配在匯編程序中進(jìn)行。匯編語言函數(shù):.mmregs.bssx1,1;為局部幀分配內(nèi)存空間.bssx0,1.bssy1,1.bssy0,1.bssw3,1.bssw2,1.bssw1,1.bssw0,1.text.global_MPY32;聲明函數(shù)名為全局變量STM#X1,AR2;令A(yù)R2指向第一個參數(shù)存放單元STM#Y1,AR3;令A(yù)R3指向第二個參數(shù)存放單元STM#W0,AR4;令A(yù)R4指向乘法結(jié)果存放單元STH,A,*AR2+;傳遞第一個參數(shù)STL,A,*AR2LD*SP(1),A;傳遞第二個參數(shù)STHA,*AR3+LD*SP(2),ASTL,A,*AR3LD#00,ALD*AR2,T;T=x0_MPY32:MPYU*AR3-,A;A=ux0*uy0STLA,*AR4-;w0=ux0*uy0LDA,-16,AMACSU*AR2-,*AR3+,A;A+=y1*ux0MACSU*AR3-,*AR2,A;A+=x1*uy0STLA,*AR4-;w1=ALDA,-16,AMAC*AR2,*AR3,A;A+=x1*y1STLA,*AR4-;為W2賦值STHA,*AR4;為W3賦值LDW3,A;將W3單元地址作為返回值,傳遞到A累加器RET匯編程序可以看出,在匯編程序中至少要為局部幀分配8個單元,其中4個單元用來存放參數(shù)值,4個單元用來存放運(yùn)算結(jié)果從C程序中訪問在匯編程序中定義的變量或常數(shù),根據(jù)變量所在的位置和屬性,可以分為以下3種情況:(1)訪問在.bss塊中定義的變量
實(shí)現(xiàn)方法如下:①用.bss或.usect偽指令定義變量②用.global偽指令定義外部變量③匯編語言中在變量名前加下劃線④在C中將變量定義成外部的,然后用普通的方式訪問。采用上述方法后,在C程序中就可以訪問這個變量6.3.2從C程序中訪問匯編程序變量例:匯編語言程序://注意變量名前都有下劃線
.bss_var,1;定義變量
.global_var;說明為外部變量C語言程序:externintvar;/*外部變量*/
var=1;/*訪問變量*/(2)訪問不在.bss塊中定義的變量
不希望變量定義在.bss段,例如一個在匯編語言中定義的數(shù)據(jù)表,不希望將它存放在RAM中。在這種情況下,必須定義一個指針指向?qū)ο?,然后在C程序中間接訪問它。所需的操作如下:定義對象,最好將其放入一個獨(dú)立的初始化段中。聲明一個全局標(biāo)號,指向?qū)ο蟮钠鹗嫉刂?。這樣對象可以被連接到存儲空間的任意位置。在C程序中,將標(biāo)號聲明為外部的,不要在標(biāo)號前加下劃線。在C程序中,定義一個指針變量指向該對象。這樣做之后就可以正常地訪問該對象了以C程序訪問匯編程序中數(shù)據(jù)表為例。匯編語言:.global_sine;定義指向該表起始的全局符號
.sect“sine_tab”;定義一個獨(dú)立的段_sine:;表起始地址.float0.0
.float0.015987
.float0.022145C語言程序:externfloatsine[];/*聲明外部數(shù)組*/
float*sine_p=sine;/*定義一個指針變量指向該數(shù)據(jù)表*/
f=sine_p[4];/*訪問sine_p*/(3)C程序中訪問匯編程序中的常量一般情況下,匯編中的常量在C程序中也定義為同樣的常量,從而避免在C程序中訪問匯編程序中的常量。對于在匯編程序中用.set和.global偽指令定義的全局常數(shù),也可以使用特殊的操作從C程序中訪問它們。在匯編中定義的常數(shù),符號表包含的是常數(shù)的值,C中定義的變量,符號表實(shí)際上包括的是變量值的地址,而非變量值本身。但編譯器不會區(qū)分符號表中的數(shù)值與地址。如果按常量名訪問,得到的將是地址為常量的存儲單元的數(shù)值。為了避免這種情況的出現(xiàn),必須用&運(yùn)算符來得到常量值。所以在C中訪問匯編中的常數(shù)_x,應(yīng)在常數(shù)名前加一個地址操作符為“&x”例:匯編語言程序:_table_size.set10000;定義常量
.global_table_size;定義為全局變量C語言程序:externinttable_size/*聲明外部變量*/#defineTABLE_SIZE((int)(&table_size))/*用地址符號指明變量*/
for(i=0;i<TABLE_SIZE;i++)/*正常使用符號*/6.3.3在C程序中直接嵌入?yún)R編語句在C程序中嵌入?yún)R編語句是一種直接的C模塊和匯編模塊接口方法。采用這種方法一方面可以在C程序中實(shí)現(xiàn)用C語言難以實(shí)現(xiàn)的一些硬件控制功能。另一方面,也可以用這種方法在C程序中的關(guān)鍵部分用匯編語句代替C語句以優(yōu)化程序。采用這種方法的一個缺點(diǎn)是它比較容易破壞C環(huán)境,因?yàn)镃編譯器在編譯嵌入了匯編語句的C程序時并不檢查或分析所嵌入的匯編語句。嵌入?yún)R編語句的方法比較簡單,只需在匯編語句的兩邊加上括號和雙引號,并且在括號前加上asm標(biāo)識符
即可,即asm(“匯編語句”)。但是,采用此種方法必須注意以下幾點(diǎn):
①括號中的匯編語句必須以標(biāo)號、空格、tab、分號開頭,這和通常的匯編編程的語法一樣。
②不要破壞C環(huán)境,因?yàn)镃編譯器并不檢查和分析嵌入的匯編語句。
③插入跳轉(zhuǎn)語句和標(biāo)號會產(chǎn)生不可預(yù)測的結(jié)果。
④匯編語句不要改變C程序中變量的值。
⑤不要在匯編語句中加入?yún)R編器選項而改變匯編環(huán)境。
例如:在程序中可用下列匯編語句實(shí)現(xiàn)一些硬件
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年陜西省中考英語試題(A卷)含解析
- 通信線路工程施工監(jiān)理規(guī)范方案
- 2014-2019年中國粉煤灰陶瓷墻地磚行業(yè)分析及投資咨詢報告
- 2024至2030年中國底/側(cè)密封條行業(yè)投資前景及策略咨詢研究報告
- 2024至2030年中國分體熱合式紗窗行業(yè)投資前景及策略咨詢研究報告
- 2024至2030年中國保險線插座數(shù)據(jù)監(jiān)測研究報告
- 2024至2030年中國L板行業(yè)投資前景及策略咨詢研究報告
- 2024年中國氬氣燈頭市場調(diào)查研究報告
- 2024年中國微波信號源市場調(diào)查研究報告
- 高中語文唐宋詩5第四課明月何時照我還-羈旅鄉(xiāng)思課件語文版選修唐宋詩詞鑒賞
- 科研倫理與學(xué)術(shù)規(guī)范期末考試
- 城軌行車組織-聯(lián)鎖故障時的列車運(yùn)行組織
- 2023年體育單招數(shù)學(xué)真題及答案
- 儲能技術(shù)在交通領(lǐng)域的應(yīng)用
- 《品牌視覺設(shè)計》課程標(biāo)準(zhǔn)(包含課程思政元素)
- 奢侈品管理概論第7章中國奢侈品市場概論
- 籃球賽參賽安全應(yīng)急預(yù)案
- 廚房設(shè)備操作與維護(hù)
- 七年級(上)道法-重點(diǎn)知識點(diǎn)歸納
- 品管圈QCC成果匯報提高母乳喂養(yǎng)成功率課件
- 滬科版八年級數(shù)學(xué)(上)期中考試基礎(chǔ)知識總結(jié)
評論
0/150
提交評論