匯編語言與C的混合編程.ppt_第1頁
匯編語言與C的混合編程.ppt_第2頁
匯編語言與C的混合編程.ppt_第3頁
匯編語言與C的混合編程.ppt_第4頁
匯編語言與C的混合編程.ppt_第5頁
已閱讀5頁,還剩31頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

本章要點,混合編程是指使用兩種或兩種以上的程序設計語言,通過相互調用、參數(shù)傳遞、共享數(shù)據(jù)結構和數(shù)據(jù)信息而形成程序的過程。采用高級語言與匯編語言混合編程,從而充分利用各種程序設計語言各自的優(yōu)勢,即程序的大部分采用高級語言編寫,以提高程序的開發(fā)效率;在某些部分利用匯編語言編寫,以提高程序的運行效率。 Turbo C嵌入?yún)R編方式 Turbo C模塊連接方式 匯編語言在Visual C+中的應用,8.1 Turbo C嵌入?yún)R編方式,C語言與匯編語言的混合編程的第一種方法是在C語言中嵌入?yún)R編語言,又稱嵌入式編程。其優(yōu)點是內嵌的匯編代碼顯得更加簡潔直觀,程序員不用考慮外部鏈接、命名以及參數(shù)傳遞協(xié)議等問題,主要缺點是代碼缺乏可移植性,功能較弱。此種方法一般只用于需要插入?yún)R編語句較少的情況。,8.1.1 嵌入?yún)R編語句格式 在Turbo C中,C程序中嵌入?yún)R編語言語句必須以關鍵字ASM開頭,其格式如下: ASM /*注釋*/ 在使用此種格式時,應注意以下幾點: (1)ASM作為關鍵字不能省略,帶有ASM標識的匯編語言代碼可以看成是C語言的部分程序代碼。當C語言編譯器遇到ASM語句時會識別并自動調用匯編語言編譯程序,將它翻譯為機器碼再嵌入到C語言程序之中。 (2)操作碼可以是處理器指令(如PUSH、MOV等),也可以是偽指令(如DB、DW、EXTERN等)。,(3)操作數(shù)是操作碼可以接受的數(shù)據(jù),可以是指令允許的立即數(shù)、寄存器名,也可以是C程序中的常量、變量和標號。 (4)C程序中嵌入的匯編代碼后可以有分號也可以無分號。如果匯編代碼后無分號則必須以換行符結束(嵌入的匯編語句是C語言中唯一可以以換行結束的語句);如果匯編代碼后有分號,則一行中可以有多條嵌入的匯編語句,但一條匯編語句不能跨越兩行。,(5)嵌入的匯編語句的注釋方式必須采用C語言的注釋方式,即必須用“/*”標識注釋的開始,用“*/”來標識注釋的結束,絕不能像純匯編那樣使用“;”來作為一條注釋的開始。 (6)如果要在C語言程序中嵌入連續(xù)多條匯編語句,可以在每行前面都加上“ASM”關鍵字,更簡單的辦法是輸入一個ASM關鍵字后,使用括號“和“將這些匯編語句括起來。,8.1.2 匯編語句訪問C語言的數(shù)據(jù) 內嵌的匯編語句除可以使用指令允許的立即數(shù)、寄存器名外,還可以使用C語言程序中的任何符號(標識符),包括變量、常量、標號、函數(shù)名、寄存器變量、函數(shù)參數(shù)等;C編譯程序自動將它們轉換成相應匯編語言指令的操作數(shù),并在標識符名前加下劃線。一般來說,只要匯編語句能夠使用存儲器操作數(shù)(地址操作數(shù)),就可以采用一個C語言程序中的符號;同樣,只要匯編語句可以用寄存器作為合法的操作數(shù),就可以使用一個寄存器變量。 對于具有內嵌匯編語句的C程序,C編譯器要調用匯編程序進行匯編。匯編程序在分析一條嵌入式匯編指令的操作數(shù)時,若遇到了一個標識符,它將在C程序的符號表中搜索該標識符,但8086寄存器名不在搜索范圍之內,而且大小寫形式的寄存器名都可以使用。,在C語言程序中使用嵌入式匯編語句時,還應注意以下幾個問題: (1)Turbo C語言中可以直接使用通用寄存器和段寄存器,只要在寄存器名前加一個下劃線就可以了。另外,C語言中使用SI和DI指針寄存器作為寄存器變量,利用AX和DX傳遞返回參數(shù)。 如果C語言函數(shù)中沒有寄存器說明,嵌入式匯編語句可以自由地把SI、DI用做暫存寄存器;如果C函數(shù)有寄存器說明,嵌入式匯編語句仍可以使用SI、DI,但最好采用C語言寄存器變量名形式。嵌入式匯編語句可以任意使用AX/BX/CX/DX寄存器,以及它們的8位形式。,(2)內嵌匯編指令可以使用轉移指令和LOOP循環(huán)指令,但是它們只能在函數(shù)體內有效,不允許進行段間轉移。由于ASM語句中不能給出標號,因而轉移指令只能使用C語言程序中標號(在C語言程序中通常是定義給GOTO語句使用的)。 (3)行內匯編語句的操作數(shù)也可以是C語言結構中的某個成員(字段),引用方法仍然采用下面的形式: 結構變量名.結構成員名 另一種引用方法是把結構變量的首地址送往某一地址寄存器,然后用該寄存器名(加方括號)再加成員名,中間用圓點隔開。,8.1.3 嵌入?yún)R編的編譯過程 C語言程序中含有嵌入式匯編語言語句時,C編譯器首先將C代碼的源程序(.c)編譯成匯編語言源文件(.asm),然后調用匯編程序Turbo Assembler將產(chǎn)生的匯編語言源文件編譯成目標文件(.obj),最后調用Tlink程序將目標文件鏈接成可執(zhí)行文件(.exe)。 Turbo C 2.0在編譯含內嵌匯編語句的程序時,只能采用命令行TCC方式,并且如果C源程序沒有使用#pragma inline預處理,必須使用-B命令行選項編譯連接。,Turbo C 2.0在處理匯編語句時要調用TASM.EXE。如果沒有TASM匯編器,可以用Microsoft公司的MASM.EXE來替代。具體的方法有3種: (1)用pctools或debug在tcc.exe中查找到TASM,并替換成MASM。 (2)把MASM.EXE拷貝或改名為TASM.EXE,放到Turbo C子目錄中。 (3)在命令行輸入以下內容:tcc b e /path/masm/exec語言源文件名,其中,-b是使用匯編開關,-e是使用另一個匯編器開關,path是MASM或其他的匯編器所在的目錄路徑。,模塊連接方式是匯編語言和C語言連接時最常用的方法。模塊連接是指分別編制匯編語言程序和C語言程序,C語言程序和匯編語言程序分別編譯后產(chǎn)生各自的目標程序.obj文件,然后通過連接程序LINK將幾個.obj目標文件合并,建立一個單獨的.exe可執(zhí)行文件。 在這一過程中,匯編語言程序被看做是C語言可以調用的函數(shù),匯編語言的程序名就是函數(shù)名。C語言像調用其他C函數(shù)一樣,通過匯編語言程序名調用匯編程序。簡單來說,就是將匯編語言程序作為C語言的外部子過程調用。,8.2 Turbo C模塊連接方式,8.2.1 混合編程的約定規(guī)則 1)命名約定 C編譯器對C源程序編譯時要將其中的變量名、過程名、函數(shù)名等標識符前加下劃線,而匯編程序在匯編時直接使用,所以被C語言調用的匯編程序的所有標識符前都要加下劃線,以保持兩者標識符一致。需要指出的是,如果是匯編語言設置采用C語言類型,則不必在標識符前加下劃線。 此外,C語言對標識符長度的要求是不超過8個字符,并且區(qū)分大小寫;而匯編語言則要求標識符長度不超過31個字符,且不區(qū)分大小寫。因此,在相互調用時,匯編源程序中的標識符最好不超過8個字符(由于Turbo C在PC上支持標識符長度達到32個字符,所以無此限制),并遵循C語言習慣采用小寫。,2)聲明約定 在C語言程序中,C對所要調用的外部過程、函數(shù)、變量均用EXTERN予以說明,并且放在主調用程序之前,一般放在各函數(shù)體外部,說明形式如下: extern 返回值類型 函數(shù)名稱(參數(shù)類型表); extern 變量類型 變量名; 其中,返回值類型和變量類型是C語言中函數(shù)、變量中所允許的任意類型,當返回值類型空缺時,默認為int型。經(jīng)過說明后,這些外部變量、過程、函數(shù)就可在C程序中直接使用。函數(shù)的參數(shù)在傳遞過程中要求參數(shù)個數(shù)、類型、順序要一一對應。 為了使匯編語言程序的標識符(子程序名和變量名)能在其他模塊可見,讓C語言程序能夠調用它,必須用public操作符定義它們。,3)寄存器使用約定 作為一個獨立的匯編語言子程序,當然要注意寄存器的保護和恢復。 對于寄存器BP、SP、DS、CS和SS,匯編語言子程序如果要使用它們,并且有可能改變它們的值,Turbo C要求進行保護。經(jīng)保護后,這些寄存器可以使用,但退出前必須加以恢復。 寄存器AX、BX、CX、DX和ES,在匯編語言子程序中通常可以任意使用,其中的AX和DX寄存器承擔了傳遞返回值的任務。標志寄存器也可以任意改變。,指針寄存器SI和DI比較特殊,因為Turbo C將它們用做了寄存器變量。如果C程序啟用了寄存器變量,則匯編語言子程序使用寄存器SI和DI前必須保護,退出前恢復。如果C程序沒有啟用寄存器變量,則匯編語言子程序不必保護寄存器SI和DI。Turbo C編譯程序提供了一個編譯選擇項(-r),它可以禁止C編譯程序使用寄存器變量。一般來說,建議總是對SI和DI寄存器進行保護。,4)存儲模式約定 存儲模式處理程序、數(shù)據(jù)、堆棧在主存中的分配和存取,決定代碼和數(shù)據(jù)的默認指針類型 。存儲模式在C語言中又稱編譯模式或主存模式。Turbo C提供了6種存儲模式,分別是:微型模式(Tiny)、小型模式(Small)、緊湊模式(Compact)、中型模式(Medium)、大型模式(Large)和巨型模式(Huge)。 為了使匯編語言程序與Turbo C語言程序連接到一起,對于匯編語言簡化段定義格式來說,兩者必須具有相同的存儲模式。匯編語言程序采用.model偽指令,Turbo C利用TCC選項-m指定各自的存儲模式。相同的存儲模式將自動產(chǎn)生相互兼容的調用和返回類型;同時,匯編程序的段定義偽指令.code、.data等也將產(chǎn)生與Turbo C相兼容的段名稱和屬性。 連接前,C語言與匯編語言程序都有各自的代碼段、數(shù)據(jù)段;而連接后,它們的代碼段、數(shù)據(jù)段就合二為一或者彼此相關。需要特別說明的是,被連接的多個目標模塊中,應當有一個并且只有一個具有起始模塊。也就是說,某個C語言程序中應有main()函數(shù),匯編語言程序不用定義起始執(zhí)行點。而且由于共用一個堆棧段,混合編程時通常匯編語言程序無須設置堆棧段。,8.2.2 匯編模塊的編譯和連接 (1)利用匯編程序編譯匯編語言程序成為.obj目標代碼文件。 (2)利用C編譯程序編譯C語言程序成為.obj目標代碼文件。 (3)利用連接程序將各個目標代碼文件連接在一起,得到可執(zhí)行程序文件。,8.2.3 混合編程的參數(shù)傳遞 1)利用堆棧傳遞參數(shù) C語言程序可以通過堆棧將參數(shù)傳遞給被調用函數(shù)。 C程序調用函數(shù)之前,先從該函數(shù)中的最右邊的參數(shù)開始依次將參數(shù)壓入堆棧,最后壓入最左邊的參數(shù),參數(shù)壓入堆棧的順序與實參表中參數(shù)的排列順序相反。當被調用函數(shù)運行結束后,壓入堆棧中的參數(shù)已無價值,C程序會立即調整堆棧指針SP,使之恢復壓入?yún)?shù)以前的值,釋放堆棧中為參數(shù)保留的空間。也就是說,堆棧的平衡是主函數(shù)程序實現(xiàn)的,子程序不必在返回時調整堆棧指針SP。這就是參數(shù)傳遞的C語言規(guī)則。,2)返回值的傳遞 被調用函數(shù)的返回值,按下列規(guī)則傳遞給調用者:如果返回值小于或等于16位,則將其存放在AX寄存器中;如果返回值是32位,則存放在DX.AX寄存器對中,其中,DX存儲高16位,AX存儲低16位;如果返回值大于32位,則存放在靜態(tài)變量存儲區(qū),AX寄存器存放指向這個存儲區(qū)的偏移地址;對于32位far指針,則還利用DX存放段地址。 由此可見,匯編語言子程序向C程序返回處理結果時,是通過AX和DX完成的。但對于不同長度的返回數(shù)據(jù),使用寄存器的情況也不同。,3)地址參數(shù)的傳遞 C語言程序的參數(shù)傳遞,可采用傳數(shù)值和傳地址兩種方式。如果參數(shù)是傳值的,可直接寫出實際參數(shù);如果參數(shù)是傳址的,則在說明中將參數(shù)類型說明為指針類型,調用時,用“&”取得變量的地址作為實參傳遞。 在匯編語言子程序中,利用基址指針BP,先取得地址,再間接取內容,修改后送回原處,同時以RET返回。 以傳址方式傳送參數(shù)時,實際被壓入堆棧的是參數(shù)所在的邏輯地址。這個地址也要分為近指針(僅含偏移地址)和遠指針(含段地址和偏移地址)。C語言程序以tiny、small、compact模式編譯時,它以near近指針傳遞地址,在堆棧占2字節(jié);如果C語言程序以medium、large、huge模式編譯,則地址是32位的遠指針,在堆棧中要占4 字節(jié)。,4)通過外部變量傳遞參數(shù) 混合編程中,參數(shù)的傳遞也可以通過共用外部變量實現(xiàn)。 C語言程序中也可使用匯編語言程序中的變量。此時,要求在匯編語言程序中將該變量用public進行說明,C程序中也必須用extern說明,并且數(shù)據(jù)類型對應一致。,8.2.4 匯編語言程序對C語言程序的調用 (1)為了使C函數(shù)對匯編語言程序可見,匯編語言程序需要對所調用的C語言函數(shù)、變量用關鍵字EXTERN進行說明 (2)參數(shù)的正確傳遞是混合編程的關鍵。 (3)若匯編語言程序以無參數(shù)的形式調用一個C語言函數(shù),那么,在C語言程序中對此函數(shù)進行定義時,函數(shù)后面應該跟一個空括號。若匯編語言子程序以傳值方式向C語言函數(shù)傳送數(shù)據(jù),則C語言函數(shù)可用基本類型對參數(shù)進行說明;若匯編語言子程序以傳址方式向C語言函數(shù)傳送數(shù)據(jù),則C語言函數(shù)應該使用指針類型對參數(shù)進行說明。,(4)若C語言函數(shù)向匯編語言程序送返回值,則C語言函數(shù)體必須用return語句返回。如果返回值是一個字,則送給AX;如果為32位,則低16位在AX中,高16位在DX中;更多的數(shù)據(jù)則利用DX:AX返回指針。若沒有返回值,可以不使用return語句。 (5)一般C語言程序具有起始模塊,即有主函數(shù)。這是由于高級語言程序假定某些初始化代碼已經(jīng)預先執(zhí)行過了,故能確信在高級語言模塊啟動時,適當?shù)某跏蓟僮饕呀?jīng)完成。這樣,程序從C語言程序開始執(zhí)行;然后調用匯編語言子程序,進而又調用C語言函數(shù)。,8.3.1 嵌入?yún)R編語句指令 在Visual C+中嵌入?yún)R編語句需要用到_asm關鍵字,這個關鍵字有兩種使用方法: (1)匯編指令塊方法:在_asm關鍵字后用一對花括號將匯編指令括起來。 (2)單條匯編指令方法:在每條匯編指令之前加_asm關鍵字。,8.3 匯編語言在Visual C+中的應用,在_asm塊中使用匯編語言應注意以下幾點: (1)嵌入?yún)R編完全支持的Intel 486指令集,允許使用MMX指令。對于還不能支持的指令,Visual C+中可以使用_EMIT偽指令來擴展。_EMIT偽指令相當于MASM中的DB,一次定義一個字節(jié)內容,且只能用于程序代碼段。 (2)嵌入?yún)R編可以使用所有的MASM表達式。 (3)_asm塊中允許使用C/C+的數(shù)據(jù)類型和對象,但不能使用MASM指示符和操作符來定義數(shù)據(jù)對象。這里需要特別指出的是,_asm塊中不允許使用MASM中的定義指示符(DB、DW、DD、DQ、DT和DF),也不允許使用DUP和THIS操作符。MASM中的結構和記錄也不再有效,嵌入?yún)R編不接受STRUCT、RECORD、WIDTH或者MASK。,(4)盡管嵌入?yún)R編不支持大多數(shù)MASM指示符,但它支持EVEN和ALIGN,當需要時,這些指示符在匯編代碼中加入NOP(空操作)指令使標號對齊到特定邊界。這樣可以使某些處理器取指令時具有更高的效率。 (5)嵌入?yún)R編不是宏匯編,不能使用MASM宏指示符(MACRO、REPT、IRC、IRP和ENDM)和宏操作符(、!、”。 (9)一般來說,不能假定某個寄存器在_asm塊開始的時候有已知的值。,在_asm塊中使用C+語言應注意以下幾點: (1)在嵌入?yún)R編中可以使用C/C+變量以及很多其他的C/C+元素,包括符號(包括標號、變量和函數(shù)名)、常量(包括符號常量和枚舉型成員)、宏定義和預處理指示符、注釋(包括“/*/”和“/”)、類型名(包括所有MASM中合法的類型)及typedef名稱(通常使用PTR和TYPE操作符,或者使用指定的的結構或枚舉成員)。 (2)在嵌入?yún)R編中,可以使用C/C+或匯編語言的基數(shù)計數(shù)法,如0x100和100H是相等的。 (3)嵌入?yún)R編中不能使用如“”一類的C/C+專用操作符。但C/C+和MASM共有的操作符(如“*”和“”操作符),被認為是匯編語言的操作符,是可以使用的。,(4)在_asm塊中可以引用所有在作用范圍內的C/C+符號,包括變量名稱、函數(shù)名稱和標號,但是不能訪問C+類的成員函數(shù)。此外,在嵌入?yún)R編中使用C/C+符號還有一些其他限制:每條匯編語句只能包含一個C/C+符號(多個符號只能出現(xiàn)在LENGTH、TYPE或SIZE表達式中);在_asm塊中引用函數(shù)必須先聲明(否則,編譯器將不能區(qū)別_asm塊中的函數(shù)名和標號);在_asm塊中不能使用對于MASM來說是保留字(不區(qū)分大小寫)的C/C+符號;在_asm塊中不能識別結構(Structure)和聯(lián)合(union)標簽。 (5)嵌入?yún)R編的一個方便之處是它可以使用名稱來引用C/C+變量。,(6)使用C/C+宏可以方便地把匯編代碼插入到源代碼中。但是這其中需要額外地注意,因為宏將會擴展到一個邏輯行中。為了不出現(xiàn)問題,可以按以下規(guī)則編寫宏: 使用括號把_asm塊包圍住。 把_asm關鍵字放在每條匯編指令之前。 使用經(jīng)典C風格的注釋(“/*內容*/”),不要使用匯編風格的注釋(“;內容”)或單行的C/C+注釋(“/內容”)。 (7)可以在C/C+程序中使用goto語句跳轉到_asm塊中的標號處,也可以在_asm塊中轉跳到_asm塊里面或外面的標號處。_asm塊內的標號是不區(qū)分大小寫的(指令、指示符等也是不區(qū)分大小寫的)。,(8)嵌入?yún)R編不僅可以編寫CC+函數(shù),還可以調用C函數(shù)(包括C庫函數(shù))和非重載的全局C+函數(shù),也可以調用任何用extern “C“說明的函數(shù),但不能調用C+的成員函數(shù)。因為所有的標準頭文件都采用extern “C“說明庫函數(shù),所以C+程序中的嵌入式匯編可以調用C庫函數(shù)。 (9)匯編語句通過參數(shù)名就可以引用參數(shù),采用return語句返回出口參數(shù)。返回值的約定是:對于小于等于32位的數(shù)據(jù)擴展為32位,存放在EAX寄存器中返回;48字節(jié)的返回值存放在EDX.EAX寄存器對中返回;更大字節(jié)數(shù)據(jù)則將它們的地址指針存放在EAX中返回。,8.3.2 調用匯編語言模塊 1)采用一致的調用協(xié)議 Visual C+語言具有3種調用協(xié)議(calling convention):_cdecl、_stdcall和_fastcall。 Visual C+默認的是_cdecl方式,按從右至左的順序壓參數(shù)入棧,由調用者把參數(shù)彈出棧,而傳送參數(shù)的內存棧是由調用者來維護的,返回值在EAX中。 Windows API則采用_stdcall方式,按從右至左的順序壓參數(shù)入棧,由被調用者把參數(shù)彈出棧,而傳送參數(shù)的內存棧是由被調用者來維護的,返回值在EAX中。_stdcall調用約定在輸出函數(shù)名前加上一個下劃線前綴,后面加上一個“”符號和其參數(shù)的字節(jié)數(shù),_fastcall調用的主要特點是

溫馨提示

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

評論

0/150

提交評論