![第6章-基于C語言的DSP芯片開發(fā)-課件_第1頁](http://file4.renrendoc.com/view/7f7baefb8a3a48599948f4ddb5221928/7f7baefb8a3a48599948f4ddb52219281.gif)
![第6章-基于C語言的DSP芯片開發(fā)-課件_第2頁](http://file4.renrendoc.com/view/7f7baefb8a3a48599948f4ddb5221928/7f7baefb8a3a48599948f4ddb52219282.gif)
![第6章-基于C語言的DSP芯片開發(fā)-課件_第3頁](http://file4.renrendoc.com/view/7f7baefb8a3a48599948f4ddb5221928/7f7baefb8a3a48599948f4ddb52219283.gif)
![第6章-基于C語言的DSP芯片開發(fā)-課件_第4頁](http://file4.renrendoc.com/view/7f7baefb8a3a48599948f4ddb5221928/7f7baefb8a3a48599948f4ddb52219284.gif)
![第6章-基于C語言的DSP芯片開發(fā)-課件_第5頁](http://file4.renrendoc.com/view/7f7baefb8a3a48599948f4ddb5221928/7f7baefb8a3a48599948f4ddb52219285.gif)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第6章基于C語言的DSP芯片開發(fā)
6.1引言6.2ANSIC編譯器6.3C語言編程基礎(chǔ)知識(shí)6.4基于C語言的DSP芯片開發(fā)的運(yùn)行環(huán)境6.5C語言與匯編語言的混合編程本章小結(jié)
思考題與習(xí)題
6.1
引言
DSP的C語言編程的主要內(nèi)容包括ANSIC語言編譯器,運(yùn)行環(huán)境,運(yùn)行支持庫的使用與建立,I/O編程,C語言編程的各種工具的使用,以及C調(diào)試器的使用等主要內(nèi)容。限于篇幅,本章主要對(duì)ANSIC編譯器和與C語言編程息息相關(guān)的運(yùn)行環(huán)境以及有關(guān)C語言基礎(chǔ)知識(shí)做一介紹。6.2ANSIC編譯器6.2.1優(yōu)化ANSIC編譯器
TMS320C3x/C4x編譯器支持ANSI(AmericanNationalStandardsInstitute)開發(fā)的C語言標(biāo)準(zhǔn)。該標(biāo)準(zhǔn)是使用最廣泛的C語言標(biāo)準(zhǔn),它規(guī)定C語言的一些特征受目標(biāo)處理器、運(yùn)行環(huán)境或主機(jī)環(huán)境影響。下面就TMS320C3x/C4xC語言的一些不同于標(biāo)準(zhǔn)C語言的特征給予介紹。
1.標(biāo)識(shí)符和常數(shù)
(1)所有標(biāo)識(shí)符的前100個(gè)字符有意義,區(qū)分大小寫。這些標(biāo)示符適用于內(nèi)部和外部的標(biāo)識(shí)符。
(2)源(主機(jī))和執(zhí)行(目標(biāo))字符集為ASCII碼,不存在多字節(jié)字符。
(3)字符常數(shù)或字符串常數(shù)中的十六進(jìn)制或八進(jìn)制轉(zhuǎn)義序列可具有高達(dá)32位的值。
(4)具有多個(gè)字符的字符常數(shù)按序列中的最后一個(gè)字符來編碼,例如:'abc'=='c'。
2.?dāng)?shù)據(jù)類型
(1)整數(shù)、雙精度等數(shù)據(jù)類型長(zhǎng)度與常見編譯器中的數(shù)據(jù)類型不同,所有的浮點(diǎn)數(shù)型都是用二進(jìn)制浮點(diǎn)數(shù)格式來表示的。
(2)?size_t(sizeof操作符的結(jié)果)定義為unsignedint。
(3)?ptrdiff_t(指針加減的結(jié)果)定義為int。
3.?dāng)?shù)據(jù)轉(zhuǎn)換
(1)浮點(diǎn)數(shù)到整數(shù)的轉(zhuǎn)換部分取整數(shù)部分。
(2)指針和整數(shù)可自由轉(zhuǎn)換。
4.表達(dá)式
(1)當(dāng)兩個(gè)帶符號(hào)的整數(shù)相除時(shí),若其中一個(gè)為負(fù),則其商為負(fù),余數(shù)的符號(hào)與分子的符號(hào)相同?!?”表示求商,“%”表示求余。帶符號(hào)的模運(yùn)算取被除數(shù)的符號(hào)。如:10/-3?=-3;-10/3?=-3;10%-3=1;-10%3?=-1
(2)帶符號(hào)數(shù)的右移為算術(shù)右移,即保留符號(hào)。
5.聲明
(1)寄存器存儲(chǔ)類對(duì)所有character、short、integer和pointer類型都有效。
(2)結(jié)構(gòu)成員不能被打包成字,除位域外,每個(gè)成員對(duì)準(zhǔn)在16位字的邊界。
(3)整數(shù)類型的位域帶有符號(hào),位域從字的低位開始被打包成字,并且不超過字邊界。
6.預(yù)處理器預(yù)處理器忽略所有不支持的#pragma偽指令,支持#pragma的偽指令見后面的內(nèi)容。
ANSIC編譯器的主要功能是:首先將DSP的C語言程序轉(zhuǎn)化為匯編語言程序,然后按匯編語言程序調(diào)試手段進(jìn)行調(diào)試;ANSIC編譯器支持代碼級(jí)調(diào)試。采用ANSIC語言進(jìn)行DSP軟件編程具有的優(yōu)點(diǎn)包括:
1.標(biāo)準(zhǔn)化
C語言是一種非常便于移植的編程語言,尤其是在語言的擴(kuò)展方面,但缺乏標(biāo)準(zhǔn)化,而ANSIC則為這些擴(kuò)展提供了新的標(biāo)準(zhǔn)。
2.兼容性
ANSIC標(biāo)準(zhǔn)是K&R標(biāo)準(zhǔn)的超集。在絕大多數(shù)編譯器下調(diào)試并運(yùn)行的程序都可以在優(yōu)化ANSIC編譯器下運(yùn)行。ANSIC的兼容性還有另一個(gè)含義,就是通過簡(jiǎn)單的修改即可適用于TI公司的其他芯片。
3.補(bǔ)充新類型補(bǔ)充的新類型主要是指新的const以及Volatile類型。它們?cè)试S對(duì)C語言程序進(jìn)行更有效的優(yōu)化。
4.改進(jìn)的函數(shù)約定函數(shù)原型允許改進(jìn)的類型檢查并允許對(duì)函數(shù)調(diào)用進(jìn)行優(yōu)化。優(yōu)化ANSIC編譯器時(shí)主要考慮了三個(gè)方面的優(yōu)化:
(1)產(chǎn)生的匯編程序在效率上可與手工編寫的匯編程序相比;
(2)提供簡(jiǎn)單的C運(yùn)行環(huán)境的程序接口,使得關(guān)鍵的DSP算法可用匯編語言實(shí)現(xiàn);
(3)為用C語言開發(fā)高性能DSP應(yīng)用程序建立一定規(guī)模的庫,它們都可以被方便地使用??偟膩碚f,優(yōu)化ANSIC編譯器的主要特征包括:
·與ANSIC功能規(guī)范完全兼容。
·具有ANSIC標(biāo)準(zhǔn)運(yùn)行支持庫。
·程序可轉(zhuǎn)化為ROM裝載的格式,可重定位、重入。
·提供與匯編語言的接口,允許對(duì)時(shí)間敏感的程序用匯編語言編寫。
·靈活而全面的鏈接器可以對(duì)內(nèi)存重定位、內(nèi)存設(shè)置、部分鏈接進(jìn)行全面的控制,而且還可以對(duì)代碼進(jìn)行運(yùn)行時(shí)的重定位。
·提供了一個(gè)外殼程序(shell),允許進(jìn)一步將C語言轉(zhuǎn)化為可執(zhí)行文件。
·快速的開發(fā)速度。
·提供大量有用的提示,以支持對(duì)C程序進(jìn)行方便的編程和調(diào)試。
·支持行內(nèi)擴(kuò)展。
·可以對(duì)庫進(jìn)行管理,包括對(duì)庫進(jìn)行文件的增加、刪除、或替換,還可以將目標(biāo)文件庫用作鏈接器的輸入。
·提供豐富的列表文件,如源代碼和匯編的交叉列表、預(yù)處理輸出文件等。
·
TMS320C3x/4xANSIC編譯器具有可為全局變量、靜態(tài)變量和常數(shù)提供無限空間的大存儲(chǔ)器模式。缺省的小存儲(chǔ)模式,其空間限制為64K字,使編碼執(zhí)行速度更快、效率更高。C外殼程序提供了許多選項(xiàng)用于控制C編譯匯編和鏈接的過程。
C語言編譯匯編和鏈接的常用的選項(xiàng)如表6.1所示。表6.1C語言編譯匯編和鏈接的常用選項(xiàng)6.2.2優(yōu)化編譯器
C編譯器提供了一個(gè)優(yōu)化編譯器。采用優(yōu)化編譯可以生成高效率的匯編代碼,從而提高程序的運(yùn)行速度,減少目標(biāo)代碼的長(zhǎng)度。在一定程度上可以認(rèn)為,C編譯器的效率主要取決于C編譯器所能進(jìn)行優(yōu)化的范圍和數(shù)量。C編譯器的優(yōu)化方法可以分為兩類,即通用優(yōu)化和特定優(yōu)化。對(duì)C語言的通用優(yōu)化的范圍主要包括:·簡(jiǎn)化表達(dá)式;·優(yōu)化數(shù)據(jù)流;·刪除公共子表達(dá)式和冗余分配;·優(yōu)化跳轉(zhuǎn);·簡(jiǎn)化控制流;·優(yōu)化與循環(huán)有關(guān)的重復(fù);·將循環(huán)體內(nèi)的計(jì)算值不變的表達(dá)式移至循環(huán)體前;·運(yùn)行支持庫函數(shù)的行內(nèi)擴(kuò)展;
對(duì)DSP芯片的特定優(yōu)化的主要內(nèi)容包括:·有效地使用寄存器;·自動(dòng)增減寄存器尋址方式;·使用塊重復(fù);·使用并行指令;·使用延遲跳轉(zhuǎn)。下面主要對(duì)浮點(diǎn)DSP芯片的特定優(yōu)化作一詳細(xì)介紹。
1)優(yōu)化寄存器變量的使用編譯器將最大程度地利用寄存器存儲(chǔ)局部變量、參數(shù)及中間值。將數(shù)據(jù)存儲(chǔ)在寄存器中要比將數(shù)據(jù)存儲(chǔ)在存儲(chǔ)器中的程序的運(yùn)行效率高。在將數(shù)組結(jié)構(gòu)轉(zhuǎn)化為循環(huán)時(shí),這一優(yōu)化顯得尤其有效。例6.1優(yōu)化寄存器變量的使用。
C語言程序:
int
gvar
;
reg(inti,intj)
{
gvar=call()&i;
j=gvar+i;
}浮點(diǎn)DSP編譯器輸出程序:
_reg:***R4分配給用戶變量i
*R5分配給用戶變量j
…
CALL_call ;R0=call()
ANDR4,R0 ;R0&=i
STIR0,@_gvar ;gvar=R0
ADDIR4,R0,R5 ;將gvar保留在R0中
… ;將結(jié)果放到R5(j)中編譯器在編譯時(shí),將i,j分別賦予R4,R5,將gvar保留在R0。這樣gvar的運(yùn)算成了3操作數(shù)運(yùn)算,結(jié)果j直接放在RS中??梢姡浞掷眉拇嫫骺商岣叱绦虻倪\(yùn)行效率。
2)效率最優(yōu)的寄存器分配編譯器根據(jù)用戶變量和中間值的類型與使用頻率來對(duì)寄存器進(jìn)行分配,在循環(huán)體內(nèi)的變量比其他變量有更高的優(yōu)先級(jí),相互之間不覆蓋的變量可以被分配給同一寄存器。
3)并行指令許多類型的指令,如裝載/裝載、存儲(chǔ)/操作/乘/加,可以配對(duì)并行執(zhí)行。當(dāng)相鄰符號(hào)滿足并行運(yùn)行的尋址要求時(shí),編譯器使它們并行運(yùn)行。雖然這一功能已由代碼生產(chǎn)工具完成,但優(yōu)化還是對(duì)提高上述情況的運(yùn)行效率起了很大的作用,因?yàn)椴僮鲾?shù)被更多地放到了寄存器中,進(jìn)一步提高了運(yùn)行速度。
4)自增尋址模式對(duì)于*P++,*--P這樣的表達(dá)式,編譯器可以使用高效的自增尋址模式。在許多場(chǎng)合,循環(huán)中的數(shù)組值被逐個(gè)使用。如:
for(i=0;i,=N;++i)a[i]…;這時(shí),編譯器通過自增寄存器變量指針把數(shù)組參數(shù)轉(zhuǎn)化為間接尋址參數(shù)。
5)塊重復(fù)浮點(diǎn)編譯器通過RPTS和RPTB指令實(shí)現(xiàn)過零循環(huán)。編譯器能發(fā)現(xiàn)通過計(jì)算機(jī)控制的循環(huán),并使用高效的RPTB和RPTS來實(shí)現(xiàn)循環(huán)。這兩種方式中,調(diào)整量可以是常數(shù),也可以是表達(dá)式。例6.2塊重復(fù),自增尋址模式和并行運(yùn)算。
C語言程序:
floata[1],b[10];
scale(floatk)
{
inti;
for(i=0;i<10;++i)
a[i]=b[i]*k;
…浮點(diǎn)DSP編譯器輸出:_scale…LDI@CONST+0,AR4 ;AR4=&a[0]LDI@CONST+1,AR5 ;AR5=&b[0]MPYFR4,*AR5++,R0 ;計(jì)算第一個(gè)結(jié)果RPTS8 ;STFR0,*AR4++ ;保存這一結(jié)果||MPYFR4,*AR5++,R0;開始計(jì)算另一個(gè)結(jié)果STFR0,*AR4++ ;保存最后一個(gè)結(jié)果
6)延遲跳轉(zhuǎn)指令浮點(diǎn)DSP支持延遲跳轉(zhuǎn)指令。它與普通的跳轉(zhuǎn)指令比起來,可以節(jié)省三個(gè)指令周期的運(yùn)行時(shí)間。延遲跳轉(zhuǎn)指令是在執(zhí)行完其后的三條指令后才發(fā)生真正的跳轉(zhuǎn),編譯器盡可能實(shí)現(xiàn)無條件的延遲跳轉(zhuǎn)指令,并在計(jì)數(shù)循環(huán)的場(chǎng)合使用條件延遲跳轉(zhuǎn)指令。例6.3延遲跳轉(zhuǎn)指令。
C語言程序:
wait(volatile
int*p)
{
for(;;)
if(*p&0x80)*p|=0xf0;
}浮點(diǎn)DSP編譯器輸出程序:
_wait:
L6:LDI*AR4,R0 ;R0=*p(AR4被分配給p)TSTB128,R0 ;test*p&0x80BZL6 ;結(jié)果為假,采用直接跳轉(zhuǎn)返回BDL6;結(jié)果為真,采用延遲跳轉(zhuǎn)返回LDI*AR4,R0 ;R0=*pOR0F0h,R0 ;R0=*p|0xF0STIR0,*AR4 ;*p=R0***BL6;結(jié)果為真時(shí)的真正跳轉(zhuǎn)發(fā)生在這里
7)使用寄存器避免沖突編譯器支持一項(xiàng)新的可選用的調(diào)用順序。它通過寄存器而非壓入堆棧的方法來避免沖突。這在程序調(diào)用時(shí),可以明顯改善程序的性能。
8)條件指令在C語言中往往有條件語句,如:
a=conditionalexpr1:expr2或(condition)a=b這時(shí)編譯器使用條件指令來減少分支。
9)循環(huán)體重復(fù)塊重復(fù)并不是用的越多越好,這要視具體情況而定。當(dāng)編譯器發(fā)現(xiàn)循環(huán)次數(shù)與循環(huán)體長(zhǎng)度都很小時(shí),它將不使用循環(huán)結(jié)構(gòu),改為使用多次重復(fù)運(yùn)行代碼段的循環(huán)體重復(fù)的方式。這樣可以避免分支或塊重復(fù)造成的跳轉(zhuǎn)或判斷開銷,提高運(yùn)行效率。6.3C語言編程基礎(chǔ)知識(shí)6.3.1數(shù)據(jù)類型所有整數(shù)類型(char、short、int、long以及對(duì)應(yīng)的無符號(hào)數(shù))都是相同的,即都是由32位的二進(jìn)制數(shù)來表示的。有符號(hào)類型由基2的補(bǔ)碼表示;字符型類型是有符號(hào)類型,等同于整型;枚舉類型的對(duì)象用32位數(shù)來表示,在表達(dá)上與整型相似;所有的浮點(diǎn)型(float、double)都是相似的,在TMS320C3x/4x中都是由32位的單精度浮點(diǎn)格式表示的;
Longdouble型浮點(diǎn)格式在TMS320C3x/4x中是由40位的擴(kuò)展精度格式表示的;數(shù)據(jù)類型的字長(zhǎng)、表達(dá)方法、數(shù)據(jù)范圍列于下表6.2;一些值的范圍在頭文件limits.h作為標(biāo)準(zhǔn)宏利用,頭文件limits.h應(yīng)用在編譯器中。注:TMS320C3x/4x類型為32位表6.2數(shù)據(jù)格式長(zhǎng)雙精度浮點(diǎn)數(shù)據(jù)類型不同于其他的浮點(diǎn)數(shù)據(jù)類型。長(zhǎng)雙精度浮點(diǎn)數(shù)據(jù)的特性如下:
(1)長(zhǎng)雙精度浮點(diǎn)數(shù)據(jù)類型不是用浮點(diǎn)和雙精度所用的單精度32位格式表示的,而是用40位擴(kuò)展精度格式表示。
(2)長(zhǎng)雙精度要求兩個(gè)存儲(chǔ)器字:第一個(gè)字保存高24位,第二個(gè)字保存低24位,操作的數(shù)據(jù)長(zhǎng)度為40位,在裝載和保存該長(zhǎng)雙精度浮點(diǎn)格式需要兩條指令。
(3)長(zhǎng)雙精度保存在一個(gè)浮點(diǎn)寄存器中,像短浮點(diǎn)和雙精度浮點(diǎn)一樣,在寄存器中傳輸參數(shù)。
(4)寄存器變量都不是40位值;因此長(zhǎng)雙精度不能通過CALL保存為寄存器變量。在CALL之前保存在存儲(chǔ)器中,在需要時(shí)還可以重新裝載。
(5)在浮點(diǎn)數(shù)/雙精度浮點(diǎn)到長(zhǎng)雙精度浮點(diǎn)轉(zhuǎn)換時(shí),40位寄存器的低8位用0填滿。在長(zhǎng)雙精度浮點(diǎn)到浮點(diǎn)/雙精度浮點(diǎn)轉(zhuǎn)換時(shí),常用RND指令把此值取舍為最接近的單精度浮點(diǎn)數(shù)值。
(6)若加、減和負(fù)值(取反)指令用擴(kuò)展精度浮點(diǎn)數(shù)作為輸入,可以用匯編指令實(shí)現(xiàn),如C3X乘法用函數(shù)MPY_LD,除法用函數(shù)DIV_LD實(shí)現(xiàn)。
(7)?40位的匯編函數(shù)鏈接到名為?.float40的自身的段中。6.3.2關(guān)鍵字
C編譯器中涉及的關(guān)鍵字主要包括C寄存器關(guān)鍵字和說明C編譯器如何訪問全局和靜態(tài)變量以及如何調(diào)用函數(shù)的near和far關(guān)鍵字。
1.C寄存器關(guān)鍵字
TMS320C3x/4x編譯器通過增加C寄存器關(guān)鍵字?jǐn)U展C語言,從而使高級(jí)語言訪問寄存器。當(dāng)用戶在目標(biāo)文件中用C寄存器關(guān)鍵字時(shí),編譯器就會(huì)把目標(biāo)文件名稱與為C3x/C4x列出的標(biāo)準(zhǔn)控制寄存器的名稱作比較。如果名稱匹配,則編譯器就生成控制寄存器的參考代碼。如果名稱不匹配,則編譯器就報(bào)告出錯(cuò)。有效的控制寄存器如表6.3所示。表6.3有效的控制寄存器
C寄存器關(guān)鍵字僅用在顯示文件中,不必在函數(shù)中作任何的聲明??蓱?yīng)用在整數(shù)或指針類型對(duì)象中,但不允許應(yīng)用在浮點(diǎn)或結(jié)構(gòu)型或邏輯對(duì)象中。
C寄存器關(guān)鍵字指明對(duì)象不能是變量。如果所用的控制寄存器是變量(即可通過外部控制來改變其值),那么這個(gè)對(duì)象也可以用變量關(guān)鍵字聲明。如果要用表6.3中的控制寄存器,用戶必須按照下面方式聲明:externcregistervolatileunsignedintregister;一旦聲明了寄存器,用戶就可以直接用這個(gè)寄存器的名稱。例6.4定義和使用控制寄存器
externcreglsgervolatileunsignedintIE;
externcreglster
volatiltunsignedintIF;
externcreglsgervolatileunsignedintIOF;
externcreglster
volatiltunsignedintST;
unsignedmyfunc{unsignedintmask}
{
while{ST&maskintmask–0}/*Donothing;wait*/;
returnIOF;
}
2.near和far關(guān)鍵字
C3x/C4x的C編譯器擴(kuò)展了C語言功能,增加的near和far關(guān)鍵字是用來說明C編譯器是如何訪問全局和靜態(tài)變量以及如何調(diào)用函數(shù)的。在句法上,near和far關(guān)鍵字被看做存儲(chǔ)類變址數(shù),它們可以出現(xiàn)在保存類聲明和類型的之前、之后和中間。兩個(gè)保存類變址不可以在一個(gè)聲明中同時(shí)應(yīng)用,例如:
farstaticintx;
staticnearintx;
staticintfatx;
farintf∞();
staticfarintf∞();
1)?near和far數(shù)據(jù)對(duì)象全局和靜態(tài)數(shù)據(jù)對(duì)象可以通過下面兩種方式訪問:near關(guān)鍵字——編譯器對(duì)數(shù)據(jù)的訪問采取相對(duì)數(shù)據(jù)頁指針方式,如:stir0,@_var
far關(guān)鍵字——編譯器不能通過DP訪問數(shù)據(jù)。但是如果數(shù)據(jù)的量大于DP所允許的32K字時(shí),就可以采用DP訪問,例如:
ldiu@cll,ar0stir0,*ar0這里cll是包含在.bss中的變量的地址。默認(rèn)情況下,編譯器產(chǎn)生小的存儲(chǔ)模型代碼,這意味每個(gè)數(shù)據(jù)對(duì)象都被當(dāng)作near關(guān)鍵字,除非它被聲明為far關(guān)鍵字。如果對(duì)象聲明為near關(guān)鍵字,一般的用相對(duì)于數(shù)據(jù)頁指針的偏移尋址。數(shù)據(jù)頁指針指向?.bss段的開始。如果-ml,-mb和-mf這些選項(xiàng)被用,則可改變默認(rèn)的設(shè)定值。大存儲(chǔ)器模型代碼,意思是每個(gè)數(shù)據(jù)對(duì)象被當(dāng)作far關(guān)鍵字來處理并生成相應(yīng)的代碼。如果用DATA_SECTION,對(duì)象就會(huì)被確認(rèn)為far變量,并且不能更改。這樣就保證對(duì)不同數(shù)據(jù)頁中的變量進(jìn)行存取。
2)?near和far函數(shù)調(diào)用函數(shù)調(diào)用可采用以下兩種方式之一
near關(guān)鍵字——編譯器假定調(diào)用的目的操作數(shù)在所調(diào)用的224字節(jié)內(nèi),編譯器用PC相對(duì)尋址方式調(diào)用指令:
call_func
far關(guān)鍵字——用戶通知編譯器調(diào)用的不在調(diào)用的224字節(jié)之內(nèi),編譯器所用的調(diào)用指令為寄存器尋址模式:
ldiu@cll,ro
callu,ro這里cll常量在.bss中為函數(shù)的地址。6.3.3寄存器變量
TMS320C3x/4xC編譯器對(duì)寄存器變量的處理依靠用戶是否用優(yōu)化器來決定。用優(yōu)化器的編譯——編譯器忽略寄存器的任何聲明,在優(yōu)化時(shí)把所有的變量都當(dāng)作寄存器變量來處理。不用優(yōu)化器的編譯——如果用戶用了寄存器關(guān)鍵字,建議把該變量分配到所選的寄存器中。8個(gè)寄存器在每個(gè)函數(shù)中都用作寄存器變量?!ぜ拇嫫鱎4和R5保留為整數(shù)寄存器變量;·
寄存器R6和R7保留為浮點(diǎn)數(shù)寄存器變量;·四個(gè)寄存器AR4~AR7保留指針或整數(shù)變量。任何標(biāo)量(整數(shù)、浮點(diǎn)數(shù)或指針)的對(duì)象都可以聲明為寄存器變量。寄存器標(biāo)示符被忽略為任何類型的對(duì)象。寄存器保存類是有其意義的參數(shù),或是邏輯變量。如果應(yīng)用基于棧的調(diào)用約定,那么聲明作寄存器的參數(shù)正常地傳入到堆棧并通過函數(shù)入口移入到寄存器中。這有利于參數(shù)在函數(shù)中訪問該參數(shù)。如果參數(shù)不被聲明為寄存器,那么參數(shù)就會(huì)在函數(shù)中分配一定的邏輯空間并保存起來,作為函數(shù)開始執(zhí)行的地方。6.3.4Pragma
指令(預(yù)處理指令)
Pragma
指令指示編譯器所對(duì)應(yīng)的處理器如何處理函數(shù)。TMS320C3x/C4xC編譯器支持下面的pragmas:
CODE_SECTION
DATA_SECTION
FUNC_CANNOT_INLINE
FUNC_EXT_CALLED
FUNC_IS_PURE
FUNC_IS_SYSTEM
FUNC_NEVER_RETURNS
FUNC_NO_GLOBAL_ASG
FUNC_NO_IND_ASG
INTERRUPT
這里所指的func和symbol必須在文件內(nèi),也就是說,用戶不能在函數(shù)體內(nèi)定義和聲明它們。即用戶必須確定該pragma在函數(shù)體外,并且必須聲明、定義所用到的func
和symbol操作。如果用戶不遵循以下規(guī)則,則編譯器會(huì)發(fā)出警告。
1)?CODE_SECTIONPragma此pragma為段名sectionname分配一個(gè)代碼空間,語法如下:#pragmaCODE_SECTION(symbol,"sectionname");該段在編譯器用?.sect匯編器指令聲明。如果段名的長(zhǎng)度大于8個(gè)字符,用戶需要應(yīng)用COFF2聲時(shí)。如果用戶想把目標(biāo)代碼與從.bss段分離出來的空間鏈接,則該pragma是有用的。例6.5CODE_SECTION預(yù)處理的使用
(a)Csourcefile
#pragmaCODE_SECTION{fn,"my_sect"}
intfn(intx)
{
returnc;
}
(b)Assemblysourcefile
.sect"my_sect"
.global_fn
2)?DATA_SECTIONPragma此pragma為段名sectionname分配一個(gè)數(shù)據(jù)空間,語法如下:
#pragmaDATA_SECTION(symbol,"sectionname");如果用戶想把目標(biāo)數(shù)據(jù)與從.bss段分離出來的空間鏈接,則該pragma是有用的。如果段名的長(zhǎng)度大于8個(gè)字符,則用戶需要應(yīng)用COFF2。例6.6DATA_SECTION預(yù)處理的使用。
(a)Csourcefile
#pragmaCODE_SECTION{fn,"my_sect"}
charbufferA[512];
charbufferB[512];
(b)Assemblysourcefile
.global_bufferA
.bss_bufferA,512
.blobal_bufferB
_bufferB: .usect"my_sect",512,1
3)?FUNC_CANNOT_INLINEPragma該pragma指示編譯器不能擴(kuò)展有名稱的函數(shù)。任何用該pragma
命名的函數(shù)優(yōu)于用戶以任何其他方式(例如用內(nèi)部的關(guān)鍵字)指出inlining。該pragma必須出現(xiàn)在聲明或用戶參考函數(shù)內(nèi)。此pragma的語法如下:
#pragmaFUNC_CANNOT_INLINE(func);自變量func
是C函數(shù)的名稱,此函數(shù)不能是內(nèi)嵌的。
4)?FUNC_EXT_CALLEDPragma當(dāng)用戶用-pm選項(xiàng)時(shí),編譯器用程序等級(jí)最優(yōu)化。當(dāng)用戶用這種最優(yōu)化的類型時(shí),編譯器將通過主函數(shù)直接或間接的去掉沒調(diào)用的函數(shù)。這樣,用戶可以通過手控代碼調(diào)用而不是用主函數(shù)。該pragma指明了優(yōu)化器可以控制C函數(shù),并調(diào)用這些C函數(shù)或其他的函數(shù)。這些函數(shù)就作為C語言的入口地址。該pragma的定義必須在聲明或用戶想引用的函數(shù)之前。語法如下:
#pragmaFUNC_EXT_CALLED(func);
變量func是用戶所定義的C函數(shù)的名稱。
5)?FUNC_IS_PUREPragma該pragma指明了優(yōu)化器對(duì)有名稱函數(shù)的影響。編譯器按照下面情況處理這種影響:
·如果函數(shù)的值不需要,則刪除調(diào)用的函數(shù);
·
刪除相同的函數(shù)。該pragma的定義必須在聲明或用到的函數(shù)之前,語法如下:
#pragmaFUNC_IS_PURE(func);變量func是C函數(shù)的名稱。
6)?FUNC_IS_SYSTEMPragma
該pragma指明優(yōu)化器可優(yōu)化有名稱的函數(shù)的行為,此行為是針對(duì)有名稱函數(shù)的ANSI標(biāo)準(zhǔn)定義的。該pragma的定義必須出現(xiàn)在聲明或所用到的函數(shù)之前,語法如下:
#pragmaFUNC_IS_SYSTEM(func);變量func是C函數(shù)的名稱,此函數(shù)被當(dāng)作ANSI標(biāo)準(zhǔn)函數(shù)來處理。
7)?FUNC_NEVER_RETURNSPragma該pragma指明優(yōu)化器優(yōu)化從不返回到所調(diào)用函數(shù)的位置。該pragma的定義必須出現(xiàn)在聲明或所用到的函數(shù)之前,語法如下:
#pragmaFUNC_NEVER_RETURNS(func);變量func是不可返回調(diào)用C函數(shù)的名稱。
8)?FUNC_NO_GLOBAL_ASGPragma該pragma指明優(yōu)化器優(yōu)化沒有配置有名稱的全局變量和不包含asm語句的函數(shù)。該pragma的定義必須出現(xiàn)在聲明或所用到的函數(shù)之前,語法如下:
#pragmaFUNC_NO_GLOBAL_ASG(func);變量func是沒有配置的C函數(shù)的名稱。
9)?FUNC_NO_IND_ASGPragma該pragma指明優(yōu)化器優(yōu)化通過指針沒有配置和不包含asm語句的函數(shù)。該pragma的定義必須出現(xiàn)在聲明或所用到的函數(shù)之前,語法如下:
#pragmaFUNC_NO_IND_ASG(func);變量func是沒有配置的C函數(shù)的名稱。
10)?INTERRUPTPragma該pragma可使用戶用C代碼直接處理中斷。變量func是函數(shù)的名稱。語法如下:
#pragmaINTERRUPT(func);除了c_int00需要保留為C程序復(fù)位中斷名稱外,其他中斷名稱都不需要遵循賦名的規(guī)則。6.3.5asm語句
TMS320C3x/C4xC編譯器允許用戶嵌套TMS320C3x/C4x匯編語言指令。Asm語句在語法構(gòu)成上與調(diào)用有名稱的asm一樣,用一個(gè)常量串聲明:
asm("assemblertext");編譯器直接把聲明串拷貝到用戶輸出文件?.assemblertext中,并且數(shù)據(jù)格式必須是雙精度的。所有的字符串輸出代碼保留它們的初始值。例如,用戶可以插入一個(gè).string命令,格式如下:
asm("STR:.string\"abc"\");所插入的代碼必須是合法的匯編語言語句。像所有的匯編語言語句一樣,這一行必須以標(biāo)識(shí)符(label)開始,接下來是空格(blank)、標(biāo)號(hào)(tab),或注釋(星號(hào)或分號(hào)開始)。編譯器不檢查字符串,如果有錯(cuò),將由匯編器檢查。若需要更多的信息,請(qǐng)參考TMS320C3x/C4x匯編語言工具用戶手冊(cè)。這里寫asm語句不必嚴(yán)格按照正常的C語言語法:它們將作為語句或聲明甚至在塊外出現(xiàn)。在編譯模塊的開始處插入即可。注意:需要特別小心用asm語句時(shí)不要破壞C環(huán)境。編譯器不檢查插入的指令。若插入跳轉(zhuǎn)和標(biāo)識(shí)符到C代碼中,則可能引起不可預(yù)料的結(jié)果;若用到改變段或其他影響匯編環(huán)境的指令也可能引起麻煩。在用優(yōu)化器對(duì)匯編語句進(jìn)行優(yōu)化時(shí)要特別小心。盡管優(yōu)化器不能刪除asm指令,但它可以重新安排asm指令附近的代碼順序,這樣就可能引起不可預(yù)料的結(jié)果。asm命令可使用戶訪問硬件,而C語言則不可以。6.3.6初始化靜態(tài)和全局變量
ANSIC標(biāo)準(zhǔn)指明在沒有初始化的靜態(tài)和全局變量時(shí),必須在程序執(zhí)行前明確地初始化(賦初始化值0)。在程序被裝載時(shí),初始化的工作就已經(jīng)完成。因?yàn)檠b載過程依靠系統(tǒng)的環(huán)境,TMS320C3x/C4xC編譯器本身不能預(yù)先初始化變量。如果用戶導(dǎo)入的程序不是預(yù)先初始化的變量,用戶必須用連接器在目標(biāo)文件中初始化變量(賦初始值0)。在連接器命令文件中,.bss段用0填充,如下:
SECTIONS
{
...
.bss:{}=0x00;
...
}由于鏈接器向輸出COFF文件中寫入了一個(gè)賦0的.bss段,這種方法可能使輸出文件的尺寸急劇增加。用常量可限定類初始化靜態(tài)和全局變量。限定類的靜態(tài)常量和全局變量初始化不同于其他類型的靜態(tài)常量和全局變量。沒有明確初始化的靜態(tài)常量和全局變量可能會(huì)在初始化前被賦0。例如:constintzero;/*maynotbeinitializedtozero*/
初始化為全局變量的所有常量被放置在.cinit段中。在表達(dá)式中,初始化為局部變量的所有常量或者放置在CONST表或者用立即尋址裝載。限定類常量的初始化值不被放在.const段,因?yàn)檫@個(gè)值必須用直接尋址對(duì)其訪問。利用小的存儲(chǔ)器模塊,如果該值被放在.const段,則要求.bss和.const段必須在同一頁中。CONST表和.const段是不一樣的。CONST表包括如下內(nèi)容:整數(shù)常量表達(dá)式的寬度多于16位;浮點(diǎn)數(shù)常量表達(dá)式為指數(shù)多于4位或尾數(shù)多于11位;整數(shù)局部變量初始化值多于16位;浮點(diǎn)數(shù)局部變量初始化值為指數(shù)多于4位或尾數(shù)多于11位;全局變量的地址;字符串常量的地址。.const段內(nèi)容如下:轉(zhuǎn)變聲明表;不許初始化全局變量的字符串常量;用作big模型的CONST表。6.4基于C語言的DSP芯片開發(fā)的運(yùn)行環(huán)境6.4.1存儲(chǔ)器模式
C編譯器把存儲(chǔ)器作為單個(gè)線性塊處理,這個(gè)線性塊被分成代碼和數(shù)據(jù)子塊。C程序生成的每個(gè)代碼和數(shù)據(jù)塊都被放置在連續(xù)的存儲(chǔ)器空間中。編譯器假定32位的目標(biāo)存儲(chǔ)器地址空間都是可利用的。特別需要注意的是由鏈接器定義的存儲(chǔ)器映射。鏈接器定義的存儲(chǔ)器映射把代碼和數(shù)據(jù)分配到目標(biāo)存儲(chǔ)器中。如果編譯器不清楚存儲(chǔ)器映射的類型,則所有位置都不能裝載代碼或數(shù)據(jù),或任何位置都被保留為I/O段。編譯器生成的可重置代碼允許鏈接器把代碼和數(shù)據(jù)分配到合適的存儲(chǔ)器空間中。例如,用戶可以用鏈接器分配全局變量到內(nèi)部快速RAM中或分配可執(zhí)行代碼到內(nèi)部ROM中。
1.C編譯器生成的段
C編譯器對(duì)C語言程序編譯后可產(chǎn)生6個(gè)重定位的代碼和數(shù)據(jù)塊,這些塊也就是所謂的段,它們可以用不同的方式分配至存儲(chǔ)器中,以符合不同系統(tǒng)配置的需要。這6個(gè)段可以分為兩種類型,一種是已初始化段,另一種是未初始化段。已初始化的段主要包含數(shù)據(jù)表和可執(zhí)行代碼。C編譯器有3個(gè)已初始化的段:.text、
.cinit和?.const。
.text段包含所有可執(zhí)行代碼以及浮點(diǎn)數(shù)常量;
.cinit段包含初始化變量和常量表;
.const段包含浮點(diǎn)數(shù)常量和swich表。未初始化段用于保留存儲(chǔ)器空間,程序可以用這些空間在運(yùn)行時(shí)創(chuàng)建和存儲(chǔ)變量。編譯器支持3個(gè)未初始化的段:.bss,.stack和.sysmem。
.bss段為全局和靜態(tài)變量保留空間,在小模型中,.bss段也為常量表保留空間。在程序運(yùn)行時(shí),C初始化程序從.cinit段中拷貝數(shù)據(jù)(可能在ROM中)并把它保存在.bss段中。
.stack段為系統(tǒng)堆棧分配空間。這時(shí)存儲(chǔ)器用作向函數(shù)傳遞變量以及分配局部變量。
.system段為存儲(chǔ)器組合或存儲(chǔ)器組,為動(dòng)態(tài)存儲(chǔ)器函數(shù)malloc、calloc和realloc分配存儲(chǔ)器空間。當(dāng)然,若C程序沒有用到這些函數(shù),編譯器就不創(chuàng)建.system段。鏈接器從不同的模式下取出的單個(gè)段并且把名字相同的段合并在一起生成輸出段。需要清楚的是匯編器可產(chǎn)生3個(gè)默認(rèn)的段((.text、.bss和.data);然而C編譯器不用.data段。
C語言程序是由編譯器的輸出段和匯編器?.data段組成的。連接器從不同的模塊取出單個(gè)的段并且把名字相同的段合并在一起生成輸出段。用戶可以把這些輸出段放在所需要的任何地址處以滿足系統(tǒng)的需要。.text、.cinit、.const和.data段在ROM或RAM中連在一起;.bss、.stack和.system段在RAM中連在一起。需要注意的是,.bss
和.const段必須被分配在同一64K的數(shù)據(jù)頁內(nèi)。
2.C系統(tǒng)堆棧
C編譯器利用TMS320C3x/C4x內(nèi)置的堆棧機(jī)制實(shí)現(xiàn)如下功能:
(1)保護(hù)函數(shù)返回的地址;
(2)分配局部變量;
(3)傳遞函數(shù)變量;
(4)保存臨時(shí)結(jié)果;
(5)保護(hù)寄存器;
(6)保護(hù)處理器的狀態(tài)。堆棧操作是從低地址向高地址增加的。編譯器利用兩個(gè)輔助寄存器來管理堆棧:SP:堆棧指針(SP),指向當(dāng)前堆棧的棧頂;
AR3:幀指針,指向當(dāng)前局部幀的開始,每一個(gè)函數(shù)調(diào)用時(shí)都要在棧頂建立一個(gè)新的局部幀,用來保存局部和臨時(shí)的變量。
C運(yùn)行環(huán)境在調(diào)用C函數(shù)時(shí)自動(dòng)管理這些寄存器。如果用戶在匯編語言使用這些堆棧,一定要確保正確的使用它們。堆棧尺寸可由鏈接器利用全局符號(hào)__STACK_SIZE來設(shè)定,對(duì)其賦值即定義堆棧的大小。默認(rèn)的堆棧大小為1K(400h)字,它適合于片內(nèi)的任何一RAM塊。用戶也可在鏈接器的命令行中利用-stack選項(xiàng)和在選項(xiàng)后用常量指明堆棧的大小,以改變堆棧的大小。在系統(tǒng)初始化后,SP所指定的地址為堆棧的的底部。這個(gè)地址為.stack段中的首地址。由于堆棧的位置是由.stack段分配所決定的,而實(shí)際的位置是在連接階段確定的。如果用戶配置的堆棧在存儲(chǔ)器的最后的段(高地址),則堆棧可在存儲(chǔ)器空間中無限增長(zhǎng)。特別注意的是,由于C編譯器不提供檢查堆棧溢出的方法,因此必須保證有足夠的空間用于堆棧;否則將發(fā)生溢出現(xiàn)象而破壞程序的運(yùn)行環(huán)境,從而導(dǎo)致程序的癱瘓。所以在編寫DSP程序和存儲(chǔ)器資源分配時(shí),要注意防止堆棧溢出的發(fā)生。
3.動(dòng)態(tài)存儲(chǔ)器分配由編譯器提供的運(yùn)行支持庫包含了幾個(gè)允許用戶在運(yùn)行時(shí)動(dòng)態(tài)分配存儲(chǔ)器函數(shù)(例如malloc、calloc和realloc)。動(dòng)態(tài)分配并不是C語言本身的標(biāo)準(zhǔn),而是由標(biāo)準(zhǔn)的運(yùn)行支持函數(shù)提供的。為全局pool或heap分配的存儲(chǔ)器定義在?.system段中。.system段的大小在鏈接時(shí)用-heap選項(xiàng)來設(shè)定,設(shè)置的方法是在-heap選項(xiàng)后面加一個(gè)常量來指定。同樣,鏈接器也創(chuàng)建一個(gè)全局符號(hào)__SYSMEM_SIZE,它的值為heap中的字?jǐn)?shù)目,默認(rèn)大小為1K字。動(dòng)態(tài)分配目標(biāo)不是直接尋址(經(jīng)常用指針訪問),并且存儲(chǔ)器區(qū)在一個(gè)獨(dú)立的塊中,因此動(dòng)態(tài)存儲(chǔ)器區(qū)甚至在小的存儲(chǔ)器模式下也有無限的尺寸。所以,即使在程序中申請(qǐng)了大的數(shù)據(jù)目標(biāo),也可以使用效率更高的小存儲(chǔ)器模式。為了在?.bss段中保留空間,用戶可用heap分配大的數(shù)組,以代替聲明為全局或靜態(tài)的。例如如下的聲明:
structbigtable[10000];用指針和調(diào)用函數(shù)來替代:
structbig*table
table=(structbig*)malloc(10000*sizeof(structbig));
4.存儲(chǔ)器大小模式編譯器支持兩個(gè)存儲(chǔ)器模式:大存儲(chǔ)器模式和小存儲(chǔ)器模式。這兩種模式影響.bss如何分配存儲(chǔ)器空間。兩種模型下的.text和/或?.cinit段的尺寸都不受限制。但兩種模型下的單個(gè)函數(shù)限制在32K字的代碼或更少內(nèi),這允許編譯器在整個(gè)函數(shù)范圍內(nèi)利用相對(duì)條件跳轉(zhuǎn)。
(1)小存儲(chǔ)器模式:編譯器默認(rèn)的存儲(chǔ)器模式。在這種模式下,要求整個(gè).bss段能匹配一個(gè)64?KB字的存儲(chǔ)器在數(shù)據(jù)頁內(nèi)。這意味著在程序中的靜態(tài)和全局?jǐn)?shù)據(jù)的空間必須小于64?K字,并且.bss也不能超過64?K字地址范圍。編譯器在運(yùn)行初始化時(shí),將數(shù)據(jù)頁指針寄存器指向.bss的開始。隨后,編譯器就可以用直接尋址(@)訪問.bss中所有的目標(biāo)(如全局變量、靜態(tài)變量和常數(shù)表),而不用修改DP寄存器。
(2)大存儲(chǔ)器模式:大模式和小模式的區(qū)別是它不限制.bss塊的大小,因此對(duì)于全局和靜態(tài)變量來說,可用空間是無限的。然而當(dāng)編譯器訪問保存在.bss中的任何全局或靜態(tài)變量時(shí),編譯器首先保證DP準(zhǔn)確的指向目標(biāo)所在的存儲(chǔ)頁。為了做到這一點(diǎn),編譯器在每次訪問靜態(tài)或全局?jǐn)?shù)據(jù)時(shí),必須用LDP或LDPK指令設(shè)置DP寄存器。由于加了這條指令,不僅增加了一個(gè)指令字,而且可能引入3個(gè)指令周期或2個(gè)指令周期。例如,下面是C編譯器生成的匯編語言,它是使用LPD指令在訪問全局變量x之前設(shè)置DP寄存器的例子:***_xisaglobalvariable***
LDP_x;1extraword,1cycle
LDI@_x,R0;3cycles(2pipelinedelays)為了應(yīng)用大存儲(chǔ)器模式,-mb選項(xiàng)調(diào)用編譯器。兩種模式下都不限制.text和.cinit段的大小,單個(gè)函數(shù)的大小限制在32K字之內(nèi)。
5.RAM和ROM模型
C編譯器產(chǎn)生的代碼適合于基于ROM系統(tǒng)中的應(yīng)用。在這樣一個(gè)系統(tǒng)中,.cinit段中的初始化表保存在ROM中。在系統(tǒng)初始化期間,C初始化程序把這些表中的數(shù)據(jù)從ROM拷貝到?.bss中。程序是直接從目標(biāo)文件裝載到存儲(chǔ)器中,然后運(yùn)行該程序的。這樣做,避免了.cinit段占用存儲(chǔ)器中的空間。用戶定義的初始化程序直接從目標(biāo)文件讀取初始化表(而不是從ROM中)并且在裝載時(shí)間(而非運(yùn)行時(shí)間)直接執(zhí)行初始化。用戶可通過應(yīng)用-cr鏈接器選項(xiàng)把部分內(nèi)容送到鏈接器。6.4.2目標(biāo)請(qǐng)求本節(jié)說明不同的數(shù)據(jù)目標(biāo)如何配置大小、排列和訪問。
1.?dāng)?shù)據(jù)類型保存所有的基本類型都是32位寬度并且保存在存儲(chǔ)器中。除了位元被合成字,其他的都不能被合并。位元以聲明的順序從低位到高位配置。并不是所有的對(duì)象有排列請(qǐng)求的類型,任何類型被保存32位字寬。結(jié)構(gòu)或數(shù)組類的單元目標(biāo)被單個(gè)保存,但單元不被排列為結(jié)構(gòu)或數(shù)據(jù)(除非單元是位元)。整數(shù)類型的char,short
int
和long與無符號(hào)的是一樣的。列舉類型的目標(biāo)作為32位的字對(duì)待。浮點(diǎn)數(shù)和雙精度類型與TMS320C3x/4x指明的32位浮點(diǎn)數(shù)格式相同。長(zhǎng)雙精度類型為40位
2.長(zhǎng)立即數(shù)
TMS320C3x/C4x指令沒有立即操作數(shù)長(zhǎng)度超過16位的。編譯器有時(shí)需要用常量長(zhǎng)度大于16位。有符號(hào)整數(shù)常量有效的非符號(hào)位多于15位,無符號(hào)整數(shù)的有效位多于16位,或浮點(diǎn)數(shù)常量的尾數(shù)有效非符號(hào)位多于11位。
3.尋址全局變量編譯器生成的全局和靜態(tài)符號(hào)的地址為變址寄存器或操作指針。因?yàn)檫@些地址為32位寬度,而立即操作數(shù)限制在16位,所以這些地址當(dāng)作長(zhǎng)常量處理。
4.字符串常量在C語言中,字符串常量以下面兩種方式應(yīng)用:
(1)初始化字符數(shù)組,例如:chars[]="abc";當(dāng)字符串被初始化時(shí),它常常被當(dāng)作已初始化數(shù)組處理,每個(gè)字符都必須被初始化。
(2)字符串用在表達(dá)式中,例如:strcpy(s,,"abc");
當(dāng)字符串用在表達(dá)式中時(shí),字符串本身用.byte匯編器指令在.const段中定義,與唯一的標(biāo)號(hào)一起指向字符串。在下面的例子中,標(biāo)號(hào)SL5指向上面例子的字符串:
.const
SL5.byte“abc”,0字符串標(biāo)號(hào)有SLn,其中n為編譯器分配的一個(gè)標(biāo)號(hào),這些標(biāo)號(hào)從0開始逐漸加1,在源模塊中所有的字符串都在編譯的匯編語言模塊的結(jié)束處定義。標(biāo)號(hào)SLn代表字符串常量的地址。編譯器用這個(gè)標(biāo)號(hào)在表達(dá)式中引用該字符串。像所有的靜態(tài)目標(biāo)一樣,為了能對(duì)這個(gè)地址訪問,它必須保存在常量表中。因此處理在.const段中保存字符串本身外,編譯器還用下面的指令保存常量表中字符串地址:.wordSLn。如果同樣的字符串在源模塊中被多次引用,則該字符串將不在存儲(chǔ)器中復(fù)制。一個(gè)確定的字符串常量所有應(yīng)用都必須先對(duì)字符串單個(gè)定義。因?yàn)樽址4嬖?const段(可能在ROM)并被分享,因此對(duì)于程序來說,修改字符串常量是不實(shí)際的。下面的例子是一個(gè)不正確的使用字符串的例子:
char*a="abc"
a[1]='x' ;/*Incorrect!*/
5.常量表常量表包含了所有編譯器訪問的所有的目標(biāo),但是字長(zhǎng)太寬時(shí)不能用作立即操作數(shù)。這樣的目標(biāo)如下:
(1)整數(shù)常量寬度多于16位;
(2)浮點(diǎn)常量指數(shù)多于4位或尾數(shù)位數(shù)多于11位;
(3)整數(shù)局部變量初始化長(zhǎng)度多于16位;
(4)浮點(diǎn)數(shù)局部變量初始化指數(shù)多于4位或尾數(shù)多于11位;
(5)全局變量的地址;
(6)字符串常量的地址。常量表僅僅是一個(gè)存儲(chǔ)器塊包含了所有的目標(biāo)。編譯器建立的常量表通過應(yīng)用.word和.float匯編指令在源模塊的結(jié)束處。表中的每一個(gè)入口占用一個(gè)字。CONST標(biāo)號(hào)為表的起始地址,例如:
CONST: .word011223344h;32bitconstant
.float3.14159265;floating–point
.word_globvar;addressofglobal
.wordSL23;addressofstring在表中的目標(biāo)用直接尋址訪問,如:
LDI@const+offset,R0在這個(gè)例子中,偏移offset被放入到所需目標(biāo)的常量表中。它與字符串常量一起,用在源模塊中明確的常量。在常量表中它們分享一個(gè)入口。在大存儲(chǔ)器模式中,常量表在.const段中建立(不能在RAM中拷貝)。編譯器必須保證DP寄存器在訪問表中的目標(biāo)之前(與訪問全局變量完全一樣)正確的裝載。這就要求在對(duì)常量表的每一次訪問時(shí)都需要LDP指令。然而,在小存儲(chǔ)器模式中,為了避免正裝載的DP被覆蓋,故要求直接尋址的所有全局變量以及常量表目標(biāo)被保存在同一存儲(chǔ)器頁中。當(dāng)然,全局變量必須保存在RAM中。對(duì)于ROM中的代碼,常量表必須在ROM中,為了在同一頁取出它們,引導(dǎo)程序必須從臨時(shí)保存在ROM的常量表拷貝到RAM中全局頁中。編譯器通過向?.cinit段中的常量表放置數(shù)據(jù)來完成該項(xiàng)工作并且在表?.bss中分配空間。這樣常量表就通過自動(dòng)操作自動(dòng)地在RAM中建立。特別需要注意是,小存儲(chǔ)器模式對(duì)全局?jǐn)?shù)據(jù)頁的總尺寸限制在為64K字以內(nèi)。正如所有的初始化一樣,用戶需要避免.cinit段要求的存儲(chǔ)器的額外應(yīng)用通過-cr鏈接器選項(xiàng)和智能的引導(dǎo)程序直接實(shí)現(xiàn)初始化。6.4.3寄存器規(guī)則在C編譯環(huán)境中,對(duì)寄存器分配和操作有嚴(yán)格的規(guī)則。如果用戶要求匯編語言程序與C程序接口,掌握這些寄存器規(guī)則是很重要的。寄存器規(guī)則明確了編譯器如何使用寄存器以及在函數(shù)調(diào)用過程中如何保護(hù)寄存器。有兩種寄存器變量:在調(diào)用時(shí)得到保護(hù)和在入口時(shí)得到保護(hù)。這兩種方式的不同在于,調(diào)用程序時(shí)保護(hù)的方法不一樣。調(diào)用函數(shù)時(shí),被調(diào)用函數(shù)的功能是保護(hù)某些寄存器,這些寄存器就不必由調(diào)用者保護(hù)。如果調(diào)用者需要使用沒有保護(hù)的寄存器,則調(diào)用者在調(diào)用函數(shù)之前必須予以保護(hù)。需要注意的是,編譯器使用寄存器的方式對(duì)是否使用優(yōu)化選項(xiàng)(-o)是不同的。對(duì)優(yōu)化編譯來說,需用額外的寄存器作為寄存器變量以提高程序的運(yùn)行效率。但是函數(shù)調(diào)用時(shí)保護(hù)寄存器的規(guī)則是一樣的。表6.4列出了編譯器如何應(yīng)用寄存器并指明了哪些寄存器在函數(shù)調(diào)用時(shí)得到保護(hù)。表6.4寄存器使用和保護(hù)規(guī)則寄存器未優(yōu)化時(shí)的使用優(yōu)化時(shí)的使用調(diào)用時(shí)的保護(hù)情況R0整數(shù)和FP表達(dá)式標(biāo)量返回值整數(shù)和FP表達(dá)式標(biāo)量返回值不保護(hù)R1整數(shù)和FP表達(dá)式整數(shù)和FP表達(dá)式不保護(hù)R2~R3整數(shù)和FP表達(dá)式整數(shù)和FP寄存器變量不保護(hù)R4~R5整數(shù)寄存器變量整數(shù)和FP寄存器變量保護(hù)整數(shù)部分R6~R7FP寄存器變量整數(shù)和FP寄存器變量整數(shù)寄存器變量保護(hù)浮點(diǎn)數(shù)部分AR0~AR1指針表達(dá)式指針表達(dá)式不保護(hù)AR2指針表達(dá)式整數(shù)和指針寄存器變量不保護(hù)AR3幀指針(FP)幀指針(FP)保護(hù)AR4~AR7指針寄存器變量指針寄存器變量保護(hù)IR0擴(kuò)展的幀偏移量擴(kuò)展的幀偏移量不保護(hù)IR1擴(kuò)展的幀偏移量整數(shù)寄存器變量不保護(hù)BK不使用整數(shù)寄存器變量不保護(hù)RS、RC、RE塊(結(jié)構(gòu))拷貝塊結(jié)構(gòu)拷貝,塊重復(fù)循環(huán),整數(shù)寄存器變量不保護(hù)SP堆棧指針堆棧指針保護(hù)DP訪問全局變量(僅大模式)訪問全局變量(僅大模式)小模式保護(hù)大模式不保護(hù)
1.寄存器變量寄存器變量是定義在寄存器而不是在存儲(chǔ)器中的局部變量或編譯器臨存值。在寄存器中保存局部變量可以加快訪問的速度,從而提高編譯代碼的執(zhí)行效率。有8個(gè)寄存器用于存儲(chǔ)寄存器變量,如表6.5所示。表6.5用于寄存器變量的寄存器上述寄存器在函數(shù)調(diào)用時(shí)得以保護(hù)。當(dāng)函數(shù)使用寄存器變量時(shí),必須在在每次使用時(shí)保護(hù)寄存器的內(nèi)容,然后在函數(shù)返回時(shí)予以恢復(fù)保存的內(nèi)容。這樣就保證了被調(diào)用函數(shù)不破壞調(diào)用者的寄存器變量。當(dāng)用戶不用優(yōu)化器時(shí),用戶用寄存器關(guān)鍵字分配寄存器變量。如果寄存器中的值在調(diào)用時(shí)需要保護(hù),那么就需要代碼生成器按照表6.4列出的分配寄存器變量。如果函數(shù)聲明的寄存器變量多于所能用的,那么多余變量被處理為自動(dòng)變量并且被保存在存儲(chǔ)器的局部幀中。當(dāng)用戶用優(yōu)化器時(shí),編譯器則忽略寄存器關(guān)鍵字,并且把所有的變量當(dāng)作寄存器變量處理。編譯器分配盡可能多的變量給寄存器,這基于變量維持的時(shí)間以及應(yīng)用變量的時(shí)間。優(yōu)化器使用的額外寄存器如表6.6所示。表6.6優(yōu)化器使用的額外寄存器一般地,未列在表6.5中的寄存器不能在函數(shù)調(diào)用時(shí)得到保護(hù),因此它們僅用作變量,該變量在任何調(diào)用時(shí)都不覆蓋。然而,如果-pm殼選項(xiàng)被用來產(chǎn)生一個(gè)匯編文件,編譯器就更加準(zhǔn)確地決定寄存器的用途并且可以安全地使用在表6.4中列出的寄存器中。
2.表達(dá)式寄存器編譯器可將那些不被用作存儲(chǔ)變量的寄存器用來存儲(chǔ)計(jì)算式的中間結(jié)果。編譯器可跟蹤每個(gè)寄存器當(dāng)前的內(nèi)容,并且以保護(hù)寄存器內(nèi)容的方式盡可能地將寄存器分配給表達(dá)式。這使得編譯器能夠重復(fù)使用寄存器數(shù)據(jù),充分利用TMS320C3x/C4x的高效的寄存器尋址模式,從而可避免對(duì)變量和常量不必要的訪問。表達(dá)寄存器中的內(nèi)容在函數(shù)調(diào)用時(shí)不被保護(hù)。當(dāng)函數(shù)調(diào)用時(shí),被用作保存臨時(shí)數(shù)據(jù)的任何寄存器在函數(shù)調(diào)用前被保存為局部幀。這樣就避免了被調(diào)用函數(shù)必須得到保護(hù)和重復(fù)使用表達(dá)式寄存器。如果編譯器需要另外一個(gè)寄存器保存計(jì)算表達(dá)式,則正被用作保存臨時(shí)數(shù)據(jù)的寄存器被保存為局部幀并用作分析表達(dá)式。
3.函數(shù)返回值一般地,當(dāng)函數(shù)返回任何類型的數(shù)據(jù)(整數(shù)、指針或浮點(diǎn)數(shù))時(shí),函數(shù)返回的值都存放在R0。然而,在寄存器變量調(diào)用規(guī)則中,指針從AR0中返回。
4.堆棧和幀指針
TMS320C3x/C4xC編譯器采用傳統(tǒng)的機(jī)制來分配局部變量(非寄存器變量)并把參數(shù)傳遞給函數(shù)。當(dāng)函數(shù)要求局部保存時(shí),函數(shù)就會(huì)在堆棧中產(chǎn)生它自己的工作區(qū)(即局部幀)。局部幀在函數(shù)調(diào)用時(shí)建立,在函數(shù)返回時(shí)撤銷并重新分配。堆棧指針(SP)和幀指針(FP)這兩個(gè)寄存器用于管理堆棧和局部幀。SP是堆棧管理的寄存器,編譯器使用SP的傳統(tǒng)方法為:隨著高地址,堆棧增加并且堆棧指針指向堆棧的頂部。寄存器AR3定義為幀指針(FP)。FP對(duì)當(dāng)前的函數(shù)來說指向局部幀起始或底部。所有在局部幀保存的所有數(shù)據(jù)用FP間接尋址。
SP和FP在函數(shù)調(diào)用時(shí)必須得到保護(hù)。函數(shù)調(diào)用自動(dòng)保護(hù)SP是因?yàn)樵谡{(diào)用函數(shù)時(shí)被壓入堆棧,從而在返回時(shí)彈出堆棧。
5.其它寄存器除了上述寄存器外,其他寄存器具有特殊的功能。數(shù)據(jù)頁指針(DP):用來訪問全局和靜態(tài)變量。在小存儲(chǔ)模式下,DP在程序開始運(yùn)行時(shí)設(shè)置并且設(shè)置后從不改變。DP在小模式下可通過匯編語言修改,此時(shí)必須給予保護(hù)。索引寄存器(IR0和IR1):用于數(shù)組下標(biāo)及偏移量超過8位時(shí)的間接尋址。另外,這兩個(gè)寄存器在不用作其它目的時(shí),優(yōu)化器把其用作通用的整數(shù)型寄存器變量。在函數(shù)調(diào)用時(shí)都不被保護(hù)。
BK寄存器:僅被優(yōu)化器用作整數(shù)寄存器變量,其值在函數(shù)調(diào)用時(shí)不被保護(hù)。塊重復(fù)寄存器(RC,RE和RS):在分配大于5個(gè)字的結(jié)構(gòu)時(shí),編譯器用以產(chǎn)生有效的塊重復(fù)操作。這些寄存器如果不被用作塊重復(fù)操作時(shí)將被用作整數(shù)寄存器變量。重復(fù)寄存器值在函數(shù)調(diào)用時(shí)不被保護(hù);因此RPTB和RPTS指令不能在循環(huán)結(jié)構(gòu)內(nèi)部。6.4.4函數(shù)結(jié)構(gòu)和調(diào)用規(guī)則
C編譯器對(duì)函數(shù)調(diào)用有一系列嚴(yán)格的規(guī)則。除了特殊的運(yùn)行支持函數(shù)外,任何函數(shù)被C函數(shù)調(diào)用或調(diào)用C函數(shù)的匯編語言時(shí)均必須遵守這個(gè)規(guī)則。否則可能破壞C運(yùn)行環(huán)境,造成程序失敗。典型的函數(shù)調(diào)用的例子如圖6.1所示。在這個(gè)例子中,表示出了函數(shù)中參數(shù)傳遞及函數(shù)應(yīng)用局部變量的情況。在調(diào)用函數(shù)之前的堆棧SP指向最后保存的寄存器,F(xiàn)P指向前一個(gè)FP。壓入自變量堆棧顯示的是在執(zhí)行已經(jīng)調(diào)用函數(shù)的第一匯編指令之前的堆棧。局部幀堆棧顯示的為所有幀分配后的堆棧。此堆棧中,SP指向最后保存的寄存器。這個(gè)例子說明了已調(diào)用函數(shù)的局部幀的分配情況。函數(shù)沒有參數(shù)傳遞給堆棧以及沒有局部變量分配給局部幀。如果用戶用寄存器參數(shù)模式,則某些變量或全部變量將通過寄存器傳遞而不是用堆棧傳遞。
1.采用標(biāo)準(zhǔn)運(yùn)行模式的函數(shù)調(diào)用一般地,采用標(biāo)準(zhǔn)運(yùn)行模式進(jìn)行函數(shù)調(diào)用時(shí),需要執(zhí)行下面一系列工作:
(1)調(diào)用程序?qū)?shù)壓入堆棧。壓入時(shí)按照反序進(jìn)行,即最右邊的參數(shù)被首先壓入,最左邊參數(shù)被最后壓入。因此,當(dāng)函數(shù)調(diào)用時(shí),把最右邊的參數(shù)放入堆棧的頂端。
(2)調(diào)用程序調(diào)用函數(shù)。
(3)當(dāng)被調(diào)用函數(shù)執(zhí)行結(jié)束時(shí),調(diào)用程序用下面指令將參數(shù)彈出堆棧:SUBIn,SP其中,n是為壓入堆棧的參數(shù)的序號(hào)。圖6.1在函數(shù)調(diào)用期間的堆棧的應(yīng)用
2.采用寄存器參數(shù)運(yùn)行模式的函數(shù)調(diào)用一般地,采用寄存器參數(shù)運(yùn)行模式進(jìn)行函數(shù)調(diào)用時(shí),需要進(jìn)行下面一系列的工作:
(1)有6個(gè)寄存器用來傳遞參數(shù)。它們是AR2、R2、R3、RC、RS和RE。按照下面用法傳遞參數(shù):①前2個(gè)浮點(diǎn)參數(shù)(float、double、longdouble)用R2和R3傳遞。②整數(shù)或指針變量用上面列出的其它寄存器傳遞,順序如6個(gè)寄存器列出的順序。注意structuresandunions作為整型自變量通過地址傳遞。③所有沒有分配給寄存器的參數(shù),或者由于類型不匹配或所有寄存器已經(jīng)用完,按照反序壓入堆棧。第7個(gè)寄存器AR0通過地址返回到structuresandunions。下面列出幾個(gè)函數(shù)原型及其寄存器的參數(shù)情況。例6.7寄存器參數(shù)規(guī)則。
intf1(int*a,intb,intc); /*函數(shù)調(diào)用*/AR2 R2R3用來放參數(shù)的寄存器
intf2(inta,floatb,int*c,structAd,floate,intf);
AR2 R2RCRSR3RE
intf3(inta,int*b,floatc,intd,floate);
R2 AR2R3RCSTACK
intf4(structxa,intb,intc,intd,inte,intf,intg,inth);
AR2 R2R3RCRSRESTACKSTACK當(dāng)一個(gè)函數(shù)在說明中用省略號(hào)表明參數(shù)數(shù)目可變時(shí),上述規(guī)則稍作變化。最后一個(gè)明確說明的參數(shù)用堆棧傳遞,這樣它的堆棧地址可用作訪問沒有說明的參數(shù)的參考,如:
intvararg(inta,intb,…);
AR2STACKSTACK…
(2)調(diào)用程序調(diào)用函數(shù)。
(3)如果有參數(shù)被壓入堆棧,則調(diào)用程序?qū)?shù)彈出堆棧。
3.支持運(yùn)行函數(shù)的寄存器變量模式運(yùn)行支持的匯編文件采用了寄存器參數(shù)調(diào)用規(guī)則的修正版本。有4個(gè)寄存器,它們是R1、R2、R3和R4,按照下面的方式傳遞參數(shù):
(1)整數(shù)、浮點(diǎn)和指針參數(shù)可在在上面列出的寄存器中傳遞;
(2)沒有分配給寄存器的參數(shù)(原因是類型不匹配或者是寄存器已用完)按照反序壓入堆棧。第5個(gè)寄存器AR0被用來通過地址返回到structuresandunions。AR0也可以用來返回指針。
4.被調(diào)用函數(shù)的工作當(dāng)一個(gè)函數(shù)被另一個(gè)函數(shù)調(diào)用時(shí),必須按照下面的步驟(1)~(7)工作。但是如果函數(shù)沒有局部變量、沒有堆棧參數(shù)和不需要保存局部臨時(shí)參數(shù)時(shí),下面的(1)和(6)不執(zhí)行。
(1)被調(diào)用函數(shù)設(shè)置局部幀。局部幀以下面的方式分配:①將原來的幀指針FP壓入堆棧保護(hù);②將新的幀指針設(shè)置為當(dāng)前的SP;③將幀的大小加到SP。
(2)如果所調(diào)用的函數(shù)改變下面任一個(gè)寄存器,則必須壓入堆棧以保護(hù)它們的值。被調(diào)用函數(shù)可能在沒有保護(hù)寄存器內(nèi)容時(shí)就修正寄存器。
(3)執(zhí)行函數(shù)代碼。
(4)若函數(shù)的返回值為整數(shù)、指針或浮點(diǎn)數(shù),函就數(shù)會(huì)把返回的值放入R0寄存器中。在修訂的寄存器參數(shù)調(diào)用規(guī)則中,指針返回到AR0寄存器。若函數(shù)返回置是一個(gè)結(jié)構(gòu),則調(diào)用函數(shù)為這個(gè)結(jié)構(gòu)分配空間,然后返回空間的地址用AR0傳遞給已調(diào)用的函數(shù)。為了返回一個(gè)結(jié)構(gòu),被調(diào)用的函數(shù)將結(jié)構(gòu)拷貝到AR0指向的存儲(chǔ)器塊中。但是調(diào)用函數(shù)如果不用返回值,則將AR0置為0,通知被調(diào)用函數(shù)不用拷貝返回結(jié)構(gòu)。在這種方式中,調(diào)用函數(shù)可智能地指定調(diào)用函數(shù)結(jié)構(gòu)返回處。例如:在語句s=f()中,s是結(jié)構(gòu),f是返回結(jié)構(gòu)的一個(gè)函數(shù),調(diào)用程序把s的地址放在AR0并且返回f。函數(shù)f直接把返回的結(jié)構(gòu)拷貝到s,自動(dòng)地執(zhí)行參數(shù)。用戶一定特別注意正確聲明返回結(jié)構(gòu)的函數(shù)。
(5)調(diào)用函數(shù)恢復(fù)所有被保護(hù)的寄存器。
(6)如有必要,撤銷局部幀。即將SP減去局部幀的大小,并且恢復(fù)原來的FP。
(7)恢復(fù)返回地址,并跳轉(zhuǎn)至該地址。函數(shù)中沒保存的寄存器可通過執(zhí)行RETS語句完成該功能。在其它函數(shù)中,編譯器把返回地址裝載到R1寄存器,并且利用延遲跳轉(zhuǎn)返回。延遲操作用來恢復(fù)寄存器的值和重新分配局部幀。
5.訪問函數(shù)參數(shù)和局部變量函數(shù)通過FP間接地訪問它的地址參數(shù)和局部非寄存器變量,F(xiàn)P總是指向局部幀的底部。因?yàn)镕P實(shí)際指向原來的FP,因而第一個(gè)局部變量尋址方法為:*+FP(1)其它的局部變量尋址方法與此相似,只不過將偏移量遞增而已,如第二個(gè)變量的尋址方法是?*+FP(2)。這種方法的最大偏移是255。當(dāng)局部變量偏移值超過255時(shí),在訪問變量時(shí),首先將偏移量值裝入到索引寄存器IRn中,然后用?*+FP(IRn)的方法尋址。與局部變量的尋址方法相同,堆棧參數(shù)的尋址也是采用FP加偏移量的尋址方法。所不同的是,這里的偏移量為負(fù)值。由于返回地址直接存在FP的下面,所以第一個(gè)函數(shù)參數(shù)的尋址方法為*-FP(2)其他參數(shù)的尋址偏移依次遞增,最大也為255,超過255時(shí)用IRn寄存器作偏移。所需注意的是,應(yīng)盡量避免使用大的偏移量,因?yàn)檫@會(huì)增加程序運(yùn)行的時(shí)間。超過255偏移量的尋址方法是:
LDIoffset,IRn
….*+FP(IRn)…采用寄存器參數(shù)時(shí),調(diào)用函數(shù)和被調(diào)用函數(shù)的類型和數(shù)量完全相符,以使調(diào)用函數(shù)可以找到參數(shù)。不用優(yōu)化編譯時(shí),編譯器需用參數(shù)傳遞寄存器進(jìn)行表達(dá)式計(jì)算,因此參數(shù)在函數(shù)調(diào)用時(shí)被拷貝到局部幀中。采用優(yōu)化以編譯時(shí),編譯器應(yīng)盡量將寄存器參數(shù)保存在原來的寄存器中。6.4.5中斷處理
C程序也可以作為中斷程序。當(dāng)C環(huán)境初始化時(shí),初始化程序并不對(duì)處理器的中斷作任何初始化操作。實(shí)際上,由于硬件復(fù)位后,所有中斷是無效的,因此系統(tǒng)中的中斷實(shí)際上并沒有被使能。若系統(tǒng)中需要中斷功能,則必須對(duì)相應(yīng)的中斷作相應(yīng)的處理,由于沒有專門的C語句對(duì)中斷進(jìn)行使能或屏蔽,因此必須嵌入asm語句。當(dāng)C程序被中斷時(shí),中斷程序必須保護(hù)所有用到的寄存器。對(duì)于擴(kuò)展精度寄存器來說,由于可能包含整數(shù)或浮點(diǎn)數(shù),而中斷程序并不能確定寄存器中數(shù)值的類型,因此,中斷程序必須保護(hù)所有的40位數(shù)據(jù)。下面給出了一個(gè)中斷服務(wù)程序寄存器保護(hù)和恢復(fù)的例子。在這個(gè)例子中有兩個(gè)局部變量,并且使用了FP、SP、ST、R3、R4和AR4等寄存器。入口保護(hù):PUSH FP ;saveoldFPLDI SP,FP ;setupnewFPADDI 2,SP ;allocatelocalframePUSH ST ;saveSTPUSH R3 ;savelower32bitsofR3PUSHF R3 ;saveupper32bitsofR3PUSH R4 ;savelower32bitsofR4PUSHF R4 ;saveupper32bitsofR3PUSH AR4 ;saveAR4ExitPOP AR4 ;restoreAR4POPF R4 ;restoreupper32bitsofR4POP R4 ;restorelower32bitsofR4POPF R3 ;restoreupper32bitsofR3POP R3 ;restorelower32bitsofR3SUBI 2,SP ;deallocatelocalframePOP FP ;restoreFramePointerPOP ST ;restoreStatusregisterreti請(qǐng)注意R3和R4的高位和低位是如何保存和和恢復(fù)的。任何擴(kuò)展精度寄存器都必須分兩部分保存。所有其它的寄存器作為整數(shù)保存。
C函數(shù)通過利用一個(gè)特殊的的函數(shù)名,可以直接處理中斷。其格式為c_intnn,其中nn為00到99的之間的兩位數(shù)。例如:c_int01就是一個(gè)有效的中斷函數(shù)名。當(dāng)編譯器遇到這些函數(shù)名中的其中一個(gè)時(shí),編譯器產(chǎn)生的代碼就允許函數(shù)從中斷陷阱中被激活。
C_int00為C程序的入口點(diǎn),是為系統(tǒng)復(fù)位中斷保留的。這個(gè)特殊的中斷程序用于系統(tǒng)的初始化和調(diào)用main函數(shù)。由于c_int00并沒有調(diào)用它的程序,因此它不需要保存任何寄存器。如果中斷程序不調(diào)用其它函數(shù),則只有那些在中斷程序中用到的寄存器才予以保護(hù)。但是,如果C中斷程序調(diào)用其它函數(shù),則中斷程序?qū)⒈Wo(hù)所有的表達(dá)式寄存器。
C中斷程序與其他的C程序一樣,因?yàn)樗梢杂芯植孔兞亢图拇嫫髯兞俊H欢谡f明中斷程序時(shí),不能有參數(shù)傳遞。下面是一個(gè)中斷程序的例子:
intdataindataout
voidc_int05()
{
Datain=sample(dataout);
}中斷程序只要按照
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 5《七律 長(zhǎng)征》 說課稿-2024-2025學(xué)年語文六年級(jí)上冊(cè)統(tǒng)編版001
- 2024年四年級(jí)英語下冊(cè) Unit 7 What's the matter第4課時(shí)說課稿 譯林牛津版001
- 18《慈母情深》說課稿-2024-2025學(xué)年統(tǒng)編版語文五年級(jí)上冊(cè)001
- 2025門窗工程承包合同
- 2025市場(chǎng)咨詢服務(wù)合同范本
- 2025嫁接種苗技術(shù)服務(wù)合同書
- 2024-2025學(xué)年高中歷史 第2單元 西方人文精神的起源及其發(fā)展 第7課 啟蒙運(yùn)動(dòng)說課稿 新人教版必修3
- 信息平臺(tái)建設(shè)合同范本
- 7 《我在這里長(zhǎng)大》第一課時(shí)(說課稿)2023-2024學(xué)年統(tǒng)編版道德與法治三年級(jí)下冊(cè)
- 書推廣合同范例
- GB/T 45006-2024風(fēng)電葉片用纖維增強(qiáng)復(fù)合材料拉擠板材
- 鍋爐、壓力容器制造質(zhì)量手冊(cè)含程序文件-符合TSG07-2019《許可規(guī)則》
- 邏輯思維訓(xùn)練500題(帶答案)
- 炎癥性腸病共識(shí)2024
- 《中等強(qiáng)國(guó)視域下韓國(guó)的“新南方政策”研究》
- 2024-2030年中國(guó)保理行業(yè)現(xiàn)狀規(guī)模及運(yùn)營(yíng)態(tài)勢(shì)分析報(bào)告
- 新版加油站全員安全生產(chǎn)責(zé)任制
- 快消品公司銷售部薪酬績(jī)效方案(快消品公司銷售KPI績(jī)效考核指標(biāo))
- 人工智能大模型
- 化學(xué)第五單元化學(xué)反應(yīng)的定量關(guān)系大單元備課-2024-2025學(xué)年九年級(jí)化學(xué)人教版(2024)上冊(cè)
- 2024年中國(guó)網(wǎng)球游戲機(jī)市場(chǎng)調(diào)查研究報(bào)告
評(píng)論
0/150
提交評(píng)論