嵌入式系統(tǒng)概論第九章_第1頁
嵌入式系統(tǒng)概論第九章_第2頁
嵌入式系統(tǒng)概論第九章_第3頁
嵌入式系統(tǒng)概論第九章_第4頁
嵌入式系統(tǒng)概論第九章_第5頁
已閱讀5頁,還剩10頁未讀 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

第9章C語言與ARM匯編的混合編程在ARM應(yīng)用系統(tǒng)開發(fā)中,若所有的編程任務(wù)均用ARM匯編語言來完成,則其工作量會非常大,并且不利于系統(tǒng)升級和應(yīng)用軟件移植。事實上,ARM體系結(jié)構(gòu)支持C程序和ARM匯編語言的混合編程。在一個完整應(yīng)用系統(tǒng)的軟件實現(xiàn)過程中,除了初始化部分和一些關(guān)鍵代碼用ARM匯編語言完成之外,其余大部分的編程任務(wù)都可以用C語言來實現(xiàn)。ARM匯編語言與C語言的混合編程通常有以下幾種技術(shù):使用內(nèi)嵌匯編器;從匯編代碼中訪問C程序全局變量;ARM匯編程序和C程序間的相互調(diào)用。目錄9.1ATPCS概述9.2使用內(nèi)嵌匯編器9.3從匯編代碼中訪問C程序全局變量9.4ARM匯編程序與C程序的互相調(diào)用9.5C語言與ARM匯編混合編程的實例習(xí)題9.1ATPCS概述ATPCS規(guī)定了ARM系統(tǒng)開發(fā)過程中子程序之間相互調(diào)用的基本規(guī)則。ATPCS強制實現(xiàn)的約定是調(diào)用者如何傳遞參數(shù)(即壓棧方法,以何種方式存放參數(shù)),被調(diào)用者如何獲取參數(shù),以何種方式傳遞函數(shù)返回值。ATPCS是系統(tǒng)相關(guān)的,因為它直接涉及到編譯器如何使用處理器提供的應(yīng)用寄存器,如編譯器使用什么寄存器作為棧指針,利用哪些寄存器傳遞參數(shù)等等。ATPCS也是應(yīng)用相關(guān)的,因為它會涉及生成代碼的大小,調(diào)試功能的支持,調(diào)用者上下文處理速度以及內(nèi)存消耗等等。因此,ATPCS的制定實際上是各種指標的一個折衷(tradeoff)。為了適應(yīng)各種需求不同的應(yīng)用,ARM制定了基本ATPCS和幾種特定的ATPCS。9.1ATPCS概述1.寄存器的使用規(guī)則在基本ATPCS中,寄存器的使用必須滿足下面的規(guī)則:

子程序間通過寄存器R0~R3來傳遞參數(shù)。這時,寄存器R0~R3可以記作A0~A3。被調(diào)用的子程序在返回前無須恢復(fù)寄存器R0~R3的內(nèi)容。在子程序中,使用寄存器R4~R11來保存局部變量。這時,寄存器R4~R11可以記為V1~V8。如果一個被調(diào)用的子程序中使用了寄存器V1~V8中的某些寄存器,則子程序在進入時必須保存這些寄存器的值,在返回前必須恢復(fù)這些寄存器的值。在Thumb程序中,通常只能使用寄存器R4~R7來保存局部變量。寄存器R12用做過程調(diào)用中間臨時寄存器IP。寄存器R13用做堆棧指針SP。在子程序中寄存器R13不能用做其它用途。寄存器SP在進入子程序時的值和退出子程序的值必須相等。寄存器R14稱為鏈接寄存器LR,它用于保存子程序的返回地址。如果在子程序中保存了返回地址,寄存器R14則可以用做其他用途。寄存器R15為程序計數(shù)器PC,不能用做其他用途。

9.1ATPCS概述2.數(shù)據(jù)棧使用規(guī)則棧是一種后進先出的數(shù)據(jù)結(jié)構(gòu),是程序運行中必不可少的一種資源?;続TPCS規(guī)定數(shù)據(jù)棧為FD類型,F(xiàn)表示FULL棧,即棧指針指向棧頂元素(最后一個入棧的數(shù)據(jù)元素),反之,如果棧指針指向與棧頂元素相鄰的一個可用數(shù)據(jù)單元時,稱為EMPTY棧(用E表示)。D表示Descending,即數(shù)據(jù)棧向內(nèi)存地址減小的方向增長,反之,稱為Ascending(用A表示)。也就是說,在基本ATPCS規(guī)定下,入棧的操作是先減棧指針,再寫入數(shù)據(jù);出棧的操作是先讀出數(shù)據(jù),再加棧指針?;続TPCS還規(guī)定對數(shù)據(jù)棧的操作是8字節(jié)對齊的,即上述對棧指針的加減操作必須是偶數(shù)個字。

9.1ATPCS概述3.參數(shù)傳遞規(guī)則根據(jù)參數(shù)個數(shù)是否固定,可以將子程序分為參數(shù)個數(shù)固定的(nonvariadic)子程序和參數(shù)個數(shù)可變的(variadic)子程序。ATPCS為這兩種子程序規(guī)定了不同的參數(shù)傳遞規(guī)則。參數(shù)個數(shù)可變的子程序參數(shù)傳遞規(guī)則對于參數(shù)個數(shù)可變的子程序,當(dāng)參數(shù)不超過4個時,可以使用寄存器R0~R3來傳遞參數(shù);當(dāng)參數(shù)超過4個時,還可以使用數(shù)據(jù)棧來傳遞參數(shù)。在傳遞參數(shù)時,將所有參數(shù)看做是存放在連續(xù)的內(nèi)存單元中的字數(shù)據(jù)。然后依次將各名字數(shù)據(jù)傳送到寄存器R0、R1、R2、R3中,如果參數(shù)多于4個,將剩余的字數(shù)據(jù)傳送到數(shù)據(jù)棧中,入棧時低地址優(yōu)先,即入棧的順序與參數(shù)順序相反,最后一個字數(shù)據(jù)先入棧。參數(shù)個數(shù)固定的子程序參數(shù)傳遞規(guī)則參數(shù)個數(shù)固定的子程序的參數(shù)傳遞規(guī)則為:第一個整數(shù)參數(shù)按序分配給R0~R3寄存器,剩余的參數(shù)按序分配給堆棧。9.1ATPCS概述3.參數(shù)傳遞規(guī)則子程序結(jié)果返回規(guī)則:結(jié)果為一個32位的整數(shù)時,可以通過寄存器R0返回。結(jié)果為一個64位整數(shù)時,可以通過R0和R1返回,依此類推。結(jié)果為一個浮點數(shù)時,可以通過浮點運算部件的寄存器f0、d0或者s0來返回。結(jié)果為一個復(fù)合型的浮點數(shù)(如復(fù)數(shù))時,可以通過寄存器f0~fN或者d0~dN來返回。對于位數(shù)更多的結(jié)果,需要通過內(nèi)存來傳遞。9.2使用內(nèi)嵌匯編器內(nèi)嵌匯編器是指包含在C編器器中的匯編器。使用內(nèi)嵌匯編器后,就可以在C源程序中直接使用大部分的ARM指令和Thumb指令,從而實現(xiàn)一些用C語言不能直接完成的一些操作,例如訪問協(xié)處理器和程序狀態(tài)寄存器PSR等,同時程序的代碼效率也比較高。9.2使用內(nèi)嵌匯編器1.內(nèi)嵌匯編的語法格式在C程序中嵌入?yún)R編語言,需要相應(yīng)的C編譯器支持。這里主要介紹ARM在ADS中集成的C編譯器armcc下的內(nèi)嵌匯編的用法。當(dāng)然,GNU的gcc也支持內(nèi)嵌匯編,若讀者需要,可查閱GNU的相關(guān)資料。armcc規(guī)定在C程序中使用關(guān)鍵詞__asm(兩個下劃線)來標識一段匯編語言程序,其格式如下:__asm{instruction[;instruction]……[instruction]}即,__asm標識的匯編程序需用花括號括住,一行可寫多條匯編指令,指令之間用分號隔開。

9.2使用內(nèi)嵌匯編器2.內(nèi)嵌匯編指令的用法內(nèi)嵌匯編指令包括大部分的ARM指令和Thumb指令,但由于它嵌入在C程序中使用,因此在用法上和普通匯編指令有所不同。內(nèi)嵌匯編指令中作為操作數(shù)的寄存器和常量可以是C表達式(包括單個變量),但表達式的結(jié)果必須是無符號整數(shù),常量前的符號“#”可以省略。內(nèi)嵌匯編指令中有些寄存器的使用與標準匯編不同。內(nèi)嵌匯編指令不支持某些偽操作和偽指令。內(nèi)嵌匯編器不支持匯編語言中所有用于內(nèi)存分配的偽操作,也不支持LDR、ADR和ADRL偽指令。內(nèi)嵌匯編代碼中SWI和BL指令的用法與標準匯編。9.3從匯編代碼中訪問C程序全局變量在ARM匯編代碼中只能通過地址間接地訪問C程序的全局變量。具體訪問方法是先用IMPORT偽操作聲明該全局變量,然后用LDR偽指令將該全局變量的地址讀到一個寄存器中,最后根據(jù)變量類型用相應(yīng)的LDR指令讀取該變量的值,用相應(yīng)的STR指令修改該變量的值。對無符號變量用以下對應(yīng)指令:char類型用LDRB/STRB指令;short類型用LDRH/STRH指令;

int類型用LDR/STR指令;注意,這里是指ARMC(armcc編譯器),short類型為16位,int類型為32位,與標準C有所不同。對于帶符號的變量,則用等價的帶符號數(shù)操作指令,如LDRSB/LDRSH等。對于小于8個字的結(jié)構(gòu)性變量,可以通過一條LDM/STM指令來讀/寫整個變量;對于結(jié)構(gòu)變量的數(shù)據(jù)成員,可以使用相應(yīng)的LDR/STR指令來訪問,但必須知道該結(jié)構(gòu)成員相對于結(jié)構(gòu)變量開始地址的偏移量。9.4ARM匯編程序與C程序的相互調(diào)用使用內(nèi)嵌匯編可以彌補C語言不能直接訪問一些硬件資源的不足。但正如前所述,內(nèi)嵌匯編是一種嵌入在C編譯器下的匯編,它本身也有一些限制。比如不支持某些機器指令,不支持大多數(shù)偽操作和偽指令,對寄存器的使用也受到一些限制。另外,內(nèi)嵌匯編器是一種高層次匯編器,它匯編的代碼并不總是非常準確,代碼效率也沒有標準的ARM匯編器(armasm)匯編的代碼效率高。還有一種在C程序中使用匯編的方法,就是C程序和ARM匯編程序的相互調(diào)用。本節(jié)通過一些例子說明C和ARM匯編的相互調(diào)用技術(shù)。雖然C程序和ARM匯編程序可以互相調(diào)用,但在實際應(yīng)用中更多的是C程序調(diào)用ARM匯編程序。9.4ARM匯編程序與C程序的相互調(diào)用1.ARM匯編程序調(diào)用C程序通過ARM匯編程序調(diào)用C程序時,C程序中不能有main函數(shù),只能有被調(diào)用的函數(shù),并且函數(shù)中必須有返回語句(return)。而作為調(diào)用者的匯編程序則必須有ENTRY偽操作,以示匯編程序為主程序,同時需要用IMPORT偽操作聲明C程序中需要調(diào)用的函數(shù)名(不是C程序名)。另外,在匯編程序中調(diào)用C函數(shù)用BL指令,參數(shù)傳遞嚴格遵守相應(yīng)的ATPCS規(guī)則。

2.C程序調(diào)用ARM匯編程序C程序調(diào)用匯編程序時,需要在程序中使用extern關(guān)鍵詞聲明被調(diào)用的匯編程序,在相應(yīng)的匯編程序中要用EXPORT偽操作聲明本程序,使得本程序可以被其他的程序調(diào)用,并且在匯編程序中不能有ENTRY偽操作,以免因入口點太多造成連接器連接失敗。參數(shù)的傳遞同樣遵守相應(yīng)的ATPCS規(guī)則。9.5C語言與ARM匯編混合編程實例

本節(jié)以北京博創(chuàng)興業(yè)科技有限公司的UP-CUPS2410試驗箱為例,給出一個C語言與ARM匯編語言編程的程序?qū)嵗?。程序很簡單,就是點亮LED數(shù)碼顯示管,但是麻雀雖小,五臟俱全。通過這個例子,讀者就可以大致了解ARM應(yīng)用程序的基本結(jié)構(gòu)和開發(fā)過程。

1.安裝U

溫馨提示

  • 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論