第7章 混合編程_第1頁
第7章 混合編程_第2頁
第7章 混合編程_第3頁
第7章 混合編程_第4頁
第7章 混合編程_第5頁
已閱讀5頁,還剩44頁未讀 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、第7章 C語言程序設(shè)計與混合編程 7.1 C語言程序設(shè)計 7.2 用用C語言和匯編語言混合編程語言和匯編語言混合編程 本章小結(jié)本章小結(jié) 習(xí)習(xí) 題題 (1) 用匯編語言開發(fā)。此方式代碼效率高,程序執(zhí)行速度快,可以充分合理地利用芯片提供的硬件資源。但程序編寫比較煩瑣,可讀性較差,可移植性較差,軟件的修改和升級困難。 (2) 用C語言開發(fā)。CCS平臺包括優(yōu)化ANSI C編譯器,從而可以在C源程序級進(jìn)行開發(fā)調(diào)試,增強軟件的可讀性,提高了軟件的開發(fā)速度,方便軟件的修改和移植。然而,C編譯器無法實現(xiàn)在任何情況下都能夠合理地利用DSP芯片的各種資源。C54x DSP軟件設(shè)計的方法通常有三種: (3) C語言

2、和匯編語言混合編程開發(fā)。采用混合編程的方法能更好地達(dá)到設(shè)計要求,完成設(shè)計任務(wù)。 1. C語言特點語言特點 C語言是國際上廣泛流行的、很有發(fā)展前途的計算機(jī)高級語言。它適合于作為系統(tǒng)描述語言,既可以用來編寫系統(tǒng)軟件,也可以用來編寫應(yīng)用軟件。 匯編語言依賴于計算機(jī)硬件,程序的可讀性和可移植性比較差。而高級語言具有很好的可移植性,但是難以實現(xiàn)匯編語言的某些功能。因為C語言仍然需要通過編譯、連接才能得到可執(zhí)行目標(biāo)程序,所以是一種高級語言。但C語言允許訪問物理地址,能進(jìn)行位操作,能實現(xiàn)匯編語言的大部分功能,能直接對硬件進(jìn)行操作。C語言正是一種既可以訪問物理地址又可以進(jìn)行位操作的高級語言,這也是其與別的高級

3、語言不同的地方。 7.1 C語言程序設(shè)計語言程序設(shè)計7.1.1 C語言特點及語法語言特點及語法C語言具有如下基本特點:(1) 語言簡潔、緊湊,使用方便、靈活。(2) 運算符豐富,表達(dá)式類型多樣化。(3) 數(shù)據(jù)結(jié)構(gòu)類型豐富,具有現(xiàn)代化語言的各種數(shù)據(jù)結(jié)構(gòu)。(4) 具有結(jié)構(gòu)化的控制語句。(5) 語法限制不太嚴(yán)格,程序設(shè)計自由度大。 (6) C語言允許訪問物理地址,能進(jìn)行位操作,能實現(xiàn)匯編語言的大部分功能,能直接對硬件進(jìn)行操作。 (1) 限定詞 可由字母、數(shù)字和下劃線組成。限定詞必須以字母或下劃線開頭。區(qū)分大小寫。 (2) 常量 常量包括整型常量(八進(jìn)制、十進(jìn)制、十六進(jìn)制、長整型),字符常量,實型常量

4、(小數(shù)形式、指數(shù)形式),字符串常量,表達(dá)式,算術(shù)表達(dá)式(整型表達(dá)式、實型表達(dá)式),邏輯表達(dá)式,字位表達(dá)式,強制類型轉(zhuǎn)換表達(dá)式,逗號表達(dá)式(順序表達(dá)式),賦值表達(dá)式,條件表達(dá)式,指針表達(dá)式。 (3) 數(shù)據(jù)定義 數(shù)據(jù)類型(int、short、long、unsigned、char、float、double、struct、union、enum)用ty-pedef定義的類型名,存儲類型(auto、static、register、extem)變量的定義形式為: 存儲類別 數(shù)據(jù)類型 變量列表; 例如:static float a,b,c;2. C語言基本語法概述語言基本語法概述 (4) 函數(shù)定義 函數(shù)的定義

5、形式為: 存儲類別 數(shù)據(jù)類型 函數(shù)名(形參表別) 函數(shù)體 (5) 語句 語句包括表達(dá)式語句、函數(shù)調(diào)用語句、控制語句、復(fù)合語句、空語句。其中控制語句包括if語句、while語句、for語句和switch語句以及break語句、continue語句、return語句、goto語句。 (6) 預(yù)處理命令 預(yù)處理命令主要是指define和include語句。 C系統(tǒng)的堆??梢酝瓿傻闹饕δ苋缦拢?* 分配局部變量;* 傳遞函數(shù)參數(shù);* 保存所調(diào)用函數(shù)的返回地址;* 保存臨時結(jié)果。6.1.2 系統(tǒng)堆棧的使用系統(tǒng)堆棧的使用 運行堆棧的增長方向是從高地址到低地址, 即入棧則地址減少,出棧則地址增加。堆棧的管

6、理者是堆棧指針SP。堆棧的容量由鏈接器(Linker)設(shè)定。 如:在鏈接命令文件(.cmd文件)中加入選項 -stack 0 x1000 則堆棧的容量被設(shè)為1000H個字。 1. 存儲器模式存儲器模式 C54x DSP定點處理器有兩種類型的存儲器模式:程序存儲器和數(shù)據(jù)存儲器。前者主要用于裝載可執(zhí)行代碼,后者主要用于裝載外部變量、靜態(tài)變量、系統(tǒng)堆棧以及一些中間運算結(jié)果。 C54x DSP的程序代碼或數(shù)據(jù)以段的形式裝載于存儲器中。C語言程序經(jīng)C編譯器編譯后,生成七個可重定位的段,其中四個被稱為已初始化段,三個被稱為未初始化段。 6.1.3 存儲器模式及分配存儲器模式及分配四個已初始化段分別是:*

7、.text段 包括可執(zhí)行代碼、字符串和編譯器產(chǎn)生的常量。* .cinit段 包括初始化變量和常量表。* .const段 包括字符串常量和以const關(guān)鍵字定義的常量。* .switch段 為.const語句建立的表格。 三個未初始化段分別是: * .bss段 保留全局和靜態(tài)變量空間。在程序開始運行時,C的引導(dǎo)(boot)程序?qū)?shù)據(jù)從.cinit段拷貝到.bss段。 * .stack段 為C的系統(tǒng)堆棧分配存儲空間,用于變量的傳遞。 * .sysmem段 為動態(tài)存儲器函數(shù)malloc、calloc、realloc分配存儲器空間。若C程序未用到此類函數(shù),則C編譯器不產(chǎn)生該段。 在編寫鏈接命令文件(.

8、cmd文件)時, .text、.cinit、.switch段通??梢枣溄拥较到y(tǒng)的ROM或者RAM中去,但是必須放在程序段(page0);.const段通??梢枣溄拥较到y(tǒng)的ROM或者RAM中去,但是必須放在數(shù)據(jù)段(pagel);而.bss、.stack和.sysmem段必須鏈接到系統(tǒng)的RAM中去,并且必須放在數(shù)據(jù)段(pagel)。由實驗程序所建的某工程的鏈接命令文件(.cmd文件),如例6.1所示?!纠纠?.1】某工程的鏈接命令文件】某工程的鏈接命令文件(.cmd文件文件) MEMORY /* TMS320C54x DSP存儲器分配 */ PAGE 0 :HPIRAM: origin = 0

9、x100, length = 0 x200 PROG: origin = 0 x2000, length = 0 x1000 PAGE 1 : DARAM1: origin = 0 x03000, length = 0 x1000 PAGE 2 : FLASHRAM: origin = 0 x8000, length = 0 x7fff SECTIONS /* 由C 定義 */.vectors : load = PROG page 0 /*中斷向量表*/.text : load = PROG page 0 /*可執(zhí)行代碼*/.cinit : load = PROG page 0 /*初始化變量

10、和常數(shù)表*/.switch : load = PROG page 0/*為.constant語句建立的表格*/.stack : load = DARAM1 page 1 /*C 系統(tǒng)堆棧*/.const : load = DARAM1 page 1 /*字符串常量和以const關(guān)鍵字定義的常量*/.bss : load = DARAM1 page 1 /*全局和靜態(tài)變量空間*/.dbuffer1024: DARAM1 page 1, align (1024).coeffs1024 : DARAM1 page 1, align (1024).hpibuffer : load = HPIRAM p

11、age 0 /*由匯編定義*/ .data : DARAM1 page 1 /*匯編定義的數(shù)據(jù)段*/ 2存儲器分配存儲器分配 C編譯器提供的運行支持函數(shù)中包含有幾個允許在運行時為變量分配存儲器的函數(shù),如malloc、calloc和recalloc。動態(tài)分配不是C語言本身的標(biāo)準(zhǔn),而是由運行支持函數(shù)所提供的。 為全局pool和heap分配的存儲器空間定義在.sysmem塊中。.sysmem段的大小可由鏈接器選項中的-heap項來設(shè)定,其方法是在-heap項后加一個常數(shù)。與堆棧類似,連接器也創(chuàng)建一個全局符號_SYSMEM_SIZE。.sysmem段的大小由_SYSMEM_SIZE的數(shù)值來確定,默認(rèn)值

12、為l K字。為了在.bss段中保留空間,對于大的數(shù)據(jù),可以用heap為其分配空間,而不將它們說明為全局或靜態(tài)的。例如,對于原定義的: struct big table1000可以改用指針并調(diào)用malloc函數(shù)來定義:struct big *tabletable=(struct big*)malloc(1000*sizeof(struct big); (1) 靜態(tài)和全局變量的存儲器分配靜態(tài)和全局變量的存儲器分配 在C程序中,靜態(tài)變量被分配一個惟一的連續(xù)空間,該空間的地址由鏈接器決定。編譯器安排這些變量的空間被分配在若干個字的長度中,以保證每個變量按字邊界對準(zhǔn)。全局變量分配到數(shù)據(jù)空間,在同一模塊中

13、定義的變量分配到同一個連續(xù)的存儲空間。 (2) 域域/結(jié)構(gòu)的對準(zhǔn)結(jié)構(gòu)的對準(zhǔn) C編譯器在為結(jié)構(gòu)分配存儲空間時,它分配足夠的字以包含所有的結(jié)構(gòu)成員。一組結(jié)構(gòu)中,每個結(jié)構(gòu)開始于字邊界。所有的非域類型對準(zhǔn)于字的邊界。對域應(yīng)分配足夠多的比特。相鄰域應(yīng)裝入一個字的相鄰比特,不能跨越兩個字,否則整個域會被分配到下一個字中。 1寄存器規(guī)則寄存器規(guī)則 在C環(huán)境中,定義了嚴(yán)格的寄存器規(guī)則。寄存器規(guī)則明確了編譯器如何使用寄存器,以及在函數(shù)的調(diào)用過程中如何保護(hù)寄存器。調(diào)用函數(shù)時,某些寄存器不必由調(diào)用者來保護(hù),而由被調(diào)用函數(shù)負(fù)責(zé)保護(hù)。如果調(diào)用者需要使用沒有保護(hù)的寄存器,則調(diào)用者在調(diào)用函數(shù)前必須對這些寄存器予以保護(hù)。在編

14、寫匯編語言和C語言的接口程序時,這些規(guī)則非常重要。如果編寫時不遵守寄存器的使用規(guī)則,則C環(huán)境將會被破壞。6.1.4 TMS320C54x DSP的的C語言規(guī)則語言規(guī)則 寄存器規(guī)則概括如下: (1) 輔助寄存器 ARl、AR6、AR7由被調(diào)用函數(shù)保護(hù),即可以在函數(shù)執(zhí)行過程中修改,但在函數(shù)返回時必須恢復(fù)。在C54x DSP中,編譯器將ARl和AR6用作寄存器變量。其中,AR1被用作第一個寄存器變量,AR6被用作第二個寄存器變量,其順序不能改變。另外五個輔助寄存器AR0、AR2、AR3、AR4、AR5則可以自由使用,即在函數(shù)執(zhí)行過程中可以對它們進(jìn)行修改,不必恢復(fù)。 (2) 棧指針SP 堆棧指針SP在

15、函數(shù)調(diào)用時必須予以保護(hù),但這種保護(hù)是自動的,即在返回時,壓入堆棧的內(nèi)容都將被彈出。 (3) ARP 在函數(shù)進(jìn)入和返回時,必須為0,即當(dāng)前輔助寄存器必須為AR0,而函數(shù)執(zhí)行時則可以是其他值。 (4) OVM 在默認(rèn)情況下,編譯器總認(rèn)為OVM是0。因此,若在匯編程序中將OVM置為1,則在返回C環(huán)境時,必須將其恢復(fù)為0。 (5) 其他狀態(tài)位和寄存器可以任意使用,不必恢復(fù)。 (1) 參數(shù)傳遞 在函數(shù)調(diào)用前,將參數(shù)以逆序壓入運行堆棧。所謂逆序,即最右邊的參數(shù)最先壓入棧,然后自右向左將參數(shù)依次壓入棧,直至第二個參數(shù)入棧完畢。對第一個參數(shù),則不需壓入堆棧,而是放入累加器A中,由A進(jìn)行傳遞。若參數(shù)是長整型和浮

16、點數(shù)時,則低位字先壓入棧,高位字后壓入棧。若參數(shù)中有結(jié)構(gòu),則調(diào)用函數(shù)先給結(jié)構(gòu)分配空間,而該空間的地址則通過累加器A傳遞給被調(diào)用函數(shù)。 一個典型的函數(shù)調(diào)用圖如圖6.1所示。在該例中,我們可以看出,參數(shù)傳遞到函數(shù),同時該函數(shù)使用了局部變量并調(diào)用另一個函數(shù)。第一個參數(shù)不由堆棧傳遞,而是放入累加器A中傳遞。(如圖6.1(b)、圖6.1(c)所示)。2函數(shù)調(diào)用規(guī)則函數(shù)調(diào)用規(guī)則 (2) 被調(diào)用函數(shù)的執(zhí)行過程 被調(diào)用函數(shù)依次執(zhí)行以下幾項任務(wù): * 如果被調(diào)用函數(shù)修改了寄存器(如AR1、AR6、AR7),則必須將它們壓棧保護(hù)。 * 當(dāng)被調(diào)用函數(shù)需分配內(nèi)存來建立局部變量及參數(shù)區(qū)時,SP向低地址移動一個常數(shù)(即S

17、P減去一個常數(shù)),該常數(shù)的計算方法如下: 常數(shù)=局部變量長度+參數(shù)區(qū)中調(diào)用其他函數(shù)的參數(shù)長度 另外,從這個例子中,我們看到了函數(shù)調(diào)用時局部幀的產(chǎn)生過程:函數(shù)調(diào)用時,編譯器在運行堆棧中建立一個幀用以存儲信息。當(dāng)前函數(shù)幀成為局部幀,C環(huán)境利用局部幀來保護(hù)調(diào)用者的有關(guān)信息、傳遞參數(shù)和為局部變量分配存儲空間。每調(diào)用一個函數(shù),就建立一個新的局部幀。局部幀空間的一部分用于分配參數(shù)區(qū)(局部參數(shù)區(qū)),被傳遞的參數(shù)放入局部參數(shù)區(qū),即壓入堆棧,再傳遞到其他被調(diào)用的函數(shù)中。圖6.1 函數(shù)調(diào)用時堆棧的使用傳遞函數(shù)調(diào)用函數(shù)低SP局部參數(shù)區(qū)局部幀返回地址參數(shù)2參數(shù)n調(diào)用者局部變量高(c)參數(shù)1累加器A傳遞函數(shù)調(diào)用函數(shù)低S

18、P返回地址參數(shù)2參數(shù)n調(diào)用者局部變量高(b)參數(shù)1累加器A調(diào)用前低SP調(diào)用者參數(shù)區(qū)調(diào)用者局部變量高(a) * 被調(diào)用函數(shù)執(zhí)行程序。 * 如果被調(diào)用函數(shù)修改了寄存器ARl、AR6和AR7,則必須予以恢復(fù)。將函數(shù)的返回值放入累加器A中。整數(shù)和指針在累加器A的低16位中返回,浮點數(shù)和長整型數(shù)在累加器A的32位中返回。如果函數(shù)返回一個結(jié)構(gòu)體,則被調(diào)用函數(shù)將結(jié)構(gòu)體的內(nèi)容拷貝到累加器A所指向的存儲器空間。如果函數(shù)沒有返回值,則將累加器A置0,撤銷為局部幀開辟的存儲空間。ARP在從函數(shù)返回時,必須為0,即當(dāng)前輔助寄存器為AR0。參數(shù)不是由被調(diào)用函數(shù)彈出堆棧的,而是由調(diào)用函數(shù)彈出的。 * SP向高地址移動一個

19、常數(shù)(即SP加上一個常數(shù)),該常數(shù)即為圖6.1(b)所確定的常數(shù),這樣就又恢復(fù)了幀和參數(shù)區(qū)。 * 被調(diào)用函數(shù)恢復(fù)所有保存的寄存器。 * 函數(shù)返回。 當(dāng)C程序編譯成匯編后, 上述過程如例6.2所示?!纠纠?.2】 be_called: ;函數(shù)入口 pshm AR6 ;保存AR6 pshn AR7 ;保存AR7 frame # -16 ;分配幀和參數(shù)區(qū) . ;函數(shù)主體 frame #16 ;恢復(fù)原來的幀和參數(shù)區(qū) popm AR7 ;恢復(fù)AR7 popm AR6 ;恢復(fù)AR6 ret ;函數(shù)返回 (4) 分配幀及使用32位內(nèi)存讀/寫指令。 * 一些C54x DSP指令提供了一次讀/寫32位的操作(

20、如DLD和DADD),因此必須保證32位對象存放在偶地址開始的內(nèi)存中。為了保證這一點,C編譯器需要初始化SP,使其為偶數(shù)值。 * 由于CALL指令使SP減1,因此SP在函數(shù)入口設(shè)置為奇數(shù);而長調(diào)用FCALL指令使SP減2,故SP在函數(shù)入口設(shè)定為偶數(shù)。 * 使用CALL指令時,應(yīng)確保PSMH指令的數(shù)目加上FRAME指令分配字的數(shù)目為奇數(shù),這樣SP就指向一個偶地址;同樣,使用長調(diào)用FCALL指令時,應(yīng)保證PSMH指令的數(shù)目與FRAME指令分配字的數(shù)目和為偶數(shù),以保證SP指向偶地址。 * 為了確保32位對象在偶地址,可通過設(shè)置SP的相對地址來實現(xiàn)。 * 由于中斷調(diào)用時不能確保SP為奇數(shù)還是偶數(shù),因此

21、,中斷分配SP指向偶數(shù)地址。 3中斷函數(shù)中斷函數(shù) C函數(shù)可以直接處理中斷。但是在用C語言編寫中斷程序時,應(yīng)注意以下幾點: (1) 中斷的使能和屏蔽由程序員自己來設(shè)置。這一點可以通過內(nèi)嵌匯編語句來控制中斷的使能和屏蔽,即通過內(nèi)嵌匯編語句來設(shè)置中斷屏蔽寄存器IMR及INTM,也可通過調(diào)用匯編程序函數(shù)來實現(xiàn)。 (2) 中斷程序不能有入口參數(shù),即使聲明,也會被忽略。 (3) 中斷子程序即使被普通的C程序調(diào)用,也是無效的,因為所有的寄存器都已經(jīng)被保護(hù)了。 (4) 將一個程序與某個中斷進(jìn)行關(guān)聯(lián)時,必須在相應(yīng)的中斷矢量處放置一條跳轉(zhuǎn)指令。采用.sect匯編指令可以建立這樣一個跳轉(zhuǎn)指令表以實現(xiàn)該功能。 (5)

22、 在匯編語言中,必須在中斷程序名前加上一個下劃線。 (6) 用C語言編寫的中斷程序必須用關(guān)鍵字interrupt說明。 (7) 中斷程序用到的所有寄存器,包括狀態(tài)寄存器都必須保護(hù)。 (8) 如果中斷程序中調(diào)用了其他的程序,則所有的寄存器都必須保護(hù)。 4.表達(dá)式分析表達(dá)式分析 當(dāng)C程序中需要計算整型表達(dá)式時,必須注意到以下幾點: (1) 算術(shù)上溢和下溢。TMS320C54x DSP采用16位操作數(shù),產(chǎn)生40位結(jié)果,算術(shù)溢出是不能以一種可預(yù)測的方式進(jìn)行處理的。 (2) 整除和取模。TMS320C54x DSP沒有直接提供整除指令,因此,所有的整除和取模運算都需要調(diào)用庫函數(shù)來實現(xiàn)。這些函數(shù)將運算表達(dá)

23、式的右操作數(shù)壓入堆棧,將左操作數(shù)放入累加器的低16位。函數(shù)的計算結(jié)果在累加器中返回。 (3) 32位表達(dá)式分析。一些運算在函數(shù)調(diào)用時并不遵循標(biāo)準(zhǔn)的C調(diào)用規(guī)則,其目的在于提高程序運行速度和減少程序代碼空間。這些運算包括通過變量的左移、右移、除法、取模和乘法。 (4) C代碼訪問16位乘法結(jié)果的高16位,而無需調(diào)用32位乘法的庫函數(shù)。訪問有符號數(shù)乘法結(jié)果和無符號數(shù)乘法結(jié)果的高16位,分別如下所示。有符號結(jié)果:int n1,n2,result;result=(long)n1*(long)n2)16;無符號結(jié)果:unsigned n1,n2,result;result=(unsigned long)n

24、1*(unsigned long)n2)16; C語言程序編寫過程步驟:(1) 編輯器編輯C程序readdata.c; (2) 編譯程序?qū)程序編譯匯編成目標(biāo)文件readdata.obj;(3) 編輯一個鏈接命令文件(.cmd文件);(4) 鏈接生成.out文件,用硬件仿真器進(jìn)行調(diào)試。 【例【例6.3】用C語言編寫C54x DSP的IO口的讀程序,實現(xiàn)從IO口地址8000H連續(xù)讀入1000個數(shù)據(jù)并存入數(shù)組中。 6.1.5 C語言程序?qū)嵗Z言程序?qū)嵗?【例【例6.3】 C程序readdata.c:#include“portio.h” /*包含頭文件portio.h*/#define RD_POR

25、T 0 x8000 /*定義輸入I/O口*/static int indata1000; /*定義全局?jǐn)?shù)組*/main()int I;for(I=0;I1000;I+)portRead(RD_PORT); /*從I/O口讀數(shù)據(jù)*/ C語言和匯編語言的混合編程有以下幾種方法:。 (1) 獨立編寫匯編程序和C程序,分開編譯或匯編,形成各自的目標(biāo)代碼模塊,再用鏈接器將C模塊和匯編模塊鏈接起來。這種方法靈活性較大,但用戶必須自己維護(hù)各匯編模塊的入口和出口代碼,自己計算傳遞的參數(shù)在堆棧中的偏移量,工作量較大,但能做到對程序的絕對控制。 (2) 在C程序中使用匯編程序中定義的變量和常量。 (3) 在C程序

26、中直接內(nèi)嵌匯編語句。用此種方法可以在C程序中實現(xiàn)C語言無法實現(xiàn)的一些硬件控制功能,如修改中斷控制寄存器,中斷標(biāo)志寄存器等。6.2 用用C語言和匯編語言混合編程語言和匯編語言混合編程6.2.1 C54x DSP混合編程方法混合編程方法 (4) 將C程序編譯生成相應(yīng)的匯編程序,手工修改和優(yōu)化C編譯器生成的匯編代碼。采用此種方法時,可以控制C編譯器,使之產(chǎn)生具有交叉列表的C程序和與之對應(yīng)的匯編程序,而程序員可以對其中的匯編語句進(jìn)行修改。優(yōu)化之后,對匯編程序進(jìn)行匯編,產(chǎn)生目標(biāo)文件。根據(jù)編者經(jīng)驗,只要程序員對C和匯編均很熟悉,這種混合匯編方法的效率可以做得很高。但是,由交叉列表產(chǎn)生的C程序?qū)?yīng)的匯編程序

27、往往讀起來頗費勁,因此對一般程序員不提倡使用這種方法。 1. 獨立的獨立的C和匯編模塊接口和匯編模塊接口 獨立的C和匯編模塊接口是一種常用的C和匯編語言接口方法。采用此方法在編寫C程序和匯編程序時,必須遵循有關(guān)的調(diào)用規(guī)則和寄存器規(guī)則。調(diào)用規(guī)則和寄存器規(guī)則已在前面作了詳述。如果遵循了這些規(guī)則,那么C和匯編語言之間的接口是非常方便的。C程序可以直接引用匯編程序中定義的變量和子程序,匯編程序也可以引用C程序中定義的變量和子程序?!纠纠?.5】 C程序:程序:extern int asmfunc( ); /*聲明外部的匯編子程序*/*注意函數(shù)名前不要加下劃線*/int gvar; /*定義全局變量*

28、/main( ) int i=5;i =asmfunc(i); /*進(jìn)行函數(shù)調(diào)用*/匯編程序:_asmfunc: ;函數(shù)名前一定要有下劃線STL A,*(_gvar) ;i的值在累加器A中ADD *(_gvar),A ;返回結(jié)果在累加器A中RET ;子程序返回 2. C程序中訪問匯編程序變量程序中訪問匯編程序變量 從C程序中訪問匯編程序中定義的變量或常數(shù)時,根據(jù)變量和常數(shù)定義的位置和方法的不同,可分為三種情況。 (1) 訪問在.bss段中定義的變量,方法如下: * 采用.bss命令定義變量; * 用.global將變量說明為外部變量; * 在匯編變量名前加下劃線“_”; * 在C程序中將變量說

29、明為外部變量,然后就可以像訪問普通變量一樣訪問它。 例如:例如:匯編程序:匯編程序: /*注意變量名前都有下劃線*/ .bss _var,1 .global _var; ;聲明為外部變量C程序:程序: external int var; /*外部變量*/ var l; (2) 訪問未在.bss段定義的變量,如當(dāng)C程序訪問在匯編程序中定義的常數(shù)表時,則方法更復(fù)雜一些。此時,定義一個指向該變量的指針,然后在C程序中間接訪問它。在匯編程序中定義此常數(shù)表時,最好定義一個單獨的段。然后,定義一個指向該表起始地址的全局標(biāo)號,可以在鏈接時將它分配至任意可用的存儲器空間。如果要在C程序中訪問它,則必須在C程序

30、中以extern方式予以聲明,并且變量名前不必加下劃線“_”。這樣就可以像訪問其他普通變量一樣進(jìn)行訪問。C程序中訪問匯編常數(shù)表如例6.6所示。【例【例6.6】C程序中訪問匯編常數(shù)表程序中訪問匯編常數(shù)表 匯編程序:匯編程序: global _sine ;定義外部變量 sect sine_tab;定義一個獨立的塊裝常數(shù)表_sine: ;常數(shù)表首址 word 0 word 50 word 100 word 200C程序:程序: extern int sine; /*定義外部變量*/ int *sine_ptr=sine; /*定義一個C指針*/ f=sine_ptr2; /*訪問sine_ptr*/

31、 (3) 對于那些在匯編中以.set和.global定義的全局常數(shù),也可以在C程序中訪問,不過要用到一些特殊的方法。一般來說,在C程序中和匯編程序中定義的變量,其符號表包含的是變量的地址。而對于匯編程序中定義的常數(shù),符號表包含的是常數(shù)值。編譯器并不能區(qū)分哪些符號表包含的是變量的地址,哪些是變量的值。因此,如果要在C程序中訪問匯編程序中的常數(shù),則不能直接用常數(shù)的符號名,而應(yīng)在常數(shù)符號名前加一個地址操作符&,以示與變量的區(qū)別,這樣才能得到常數(shù)值。例如:例如:匯編程序:_tab_size .set 1000 .global _tab_sizeC程序:extern int _tab_size;

32、#define TAB_SIZE (int)(&tab_size);for(i=0; i TAB_SIZE; +i) 3. C程序中直接嵌入?yún)R編語句程序中直接嵌入?yún)R編語句 在C程序中直接嵌入?yún)R編語句是一種直接的C和匯編的接口方法。此種方法可以在C程序中實現(xiàn)C語言無法實現(xiàn)的一些硬件控制功能,如修改中斷控制寄存器、中斷標(biāo)志寄存器等。 嵌入?yún)R編語句的方法比較簡單,只需在匯編語句的兩邊加上雙引號和括號,并且在括號前加上asm標(biāo)識符即可。即: asm(“ 匯編語句 ”);如:asm ( RSBX INTM );/*開中斷*/ asm ( SSBX XF ); /*XF置高電平*/ asm ( N

33、OP ); 注意:括號中引號內(nèi)的匯編語句的語法和通常的匯編編程的語法一樣。不要破壞C環(huán)境,因為C編譯器并不檢查和分析嵌入的匯編語句。插入跳轉(zhuǎn)語句和標(biāo)號會產(chǎn)生不可預(yù)測的結(jié)果。不要讓匯編語句改變C程序中變量的值。不要在匯編語句中加入?yún)R編器選項而改變匯編環(huán)境。 修改編譯器的輸出可以控制C編譯器,從而產(chǎn)生具有交叉列表的匯編程序。而程序員可以對其中的匯編語句進(jìn)行修改,之后再對匯編程序進(jìn)行匯編,可產(chǎn)生最終的目標(biāo)文件。注意,修改匯編語句時切勿破壞C環(huán)境。6.2.2 混合編程實例混合編程實例【例【例6.7】 用混合編程的設(shè)計方法實現(xiàn)四個數(shù)碼管同時循環(huán)顯示09十個數(shù),每次顯示的數(shù)以1遞增。 C語言設(shè)計的主程序如

34、下:ioport unsigned port0;/控制數(shù)碼管選通的控制接口地址為0ioport unsigned port1;/向數(shù)碼管送顯示內(nèi)容的數(shù)據(jù)接口地址為1 /*發(fā)光二極管的顯示代碼*/char leddisp =0 xf6,0 x77,0 x14,0 xb3,0 xb6,0 xd4,0 xe6,0 xe7,0 x34,0 xf7;void main() char ledcnt=0 ; c54_init(); /*調(diào)用5402芯片初始化函數(shù)*/ for (;) ledcnt = (ledcnt+1)%10 ; /*模10循環(huán)遞增*/port0 = 0 xf ;/*向地址為0的口送1111b:四個數(shù)碼管均選通*/port1 = leddispledcnt;/*向地址為1的口送欲顯示之?dāng)?shù)*/delay3() ; /*調(diào)用延時函數(shù),停頓片刻*/ 用匯編程序設(shè)計對5402芯片初始化的函數(shù)如下:.title C54_INIT.ASM.mmregs .def _c54_init

溫馨提示

  • 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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論