《匯編語言與接口技術(shù)》第五章-子程序設(shè)計(jì)_第1頁
《匯編語言與接口技術(shù)》第五章-子程序設(shè)計(jì)_第2頁
《匯編語言與接口技術(shù)》第五章-子程序設(shè)計(jì)_第3頁
《匯編語言與接口技術(shù)》第五章-子程序設(shè)計(jì)_第4頁
《匯編語言與接口技術(shù)》第五章-子程序設(shè)計(jì)_第5頁
已閱讀5頁,還剩71頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

1、第五章 子程序設(shè)計(jì)張華平 副教授 博士Email: kevinzhangWebsite: http:/ICTCLAS張華平博士大數(shù)據(jù)搜索挖掘?qū)嶒?yàn)室 (wSMSBIT)(1)【重點(diǎn)講解】子程序基本知識(shí)、參數(shù)傳遞(2)【重點(diǎn)講解】C語言程序的反匯編(3)【一般性講解】子程序特殊應(yīng)用、模塊化程序設(shè)計(jì)、混合編程5.1 子程序基本知識(shí)5.1.1、子程序定義在匯編語言中用過程定義偽指令定義子程序。過程定義偽指令格式:過程名PROC 屬型過程名ENDP設(shè)計(jì)子程序時(shí)應(yīng)注意的問題1寄存器的保存與恢復(fù)為了保證調(diào)用程序的寄存器內(nèi)容不被破壞,應(yīng)在子程序開頭保存它要用到的寄存器內(nèi)容,返回前再恢復(fù)它們。2注意堆棧狀態(tài)在設(shè)

2、計(jì)含有子程序的程序時(shí),要密切注意堆棧的變化。這包括要注意一切與堆棧有關(guān)的操作。例如CALL調(diào)用類型和子程序定義類型的一致性,PUSH和POP指令的匹配,通過堆棧傳遞參數(shù)時(shí)子程序返回使用RET n指令等,以確保堆棧平衡。3子程序說明 為便于引用,子程序應(yīng)在開頭對(duì)其功能、調(diào)用參數(shù)和返回參數(shù)等予以說明,例如參數(shù)的類型、格式及存放位置等。北京理工大學(xué)-張華平-201175.1.2 堆 棧 所謂堆棧,就是供程序使用的一塊連續(xù)的內(nèi)存空間,一般用于保存和讀取臨時(shí)性的數(shù)據(jù)。北京理工大學(xué)-張華平-201181. 堆棧特點(diǎn) 1. 臨時(shí)性2. 快速性3. 動(dòng)態(tài)擴(kuò)展性北京理工大學(xué)-張華平-201192. 堆棧用途 1

3、. 保護(hù)和恢復(fù)調(diào)用現(xiàn)場(chǎng)2. 用于變量之間的數(shù)據(jù)傳遞3. 用做臨時(shí)的數(shù)據(jù)區(qū)4. 子程序的調(diào)用和返回PUSH EAXPUSH EBXPOP EBXPOP EAX1. 保護(hù)和恢復(fù)調(diào)用現(xiàn)場(chǎng)PUSH Var1POP Var2下面的兩條指令交換兩個(gè)變量Var1和Var2的值。PUSH Var1PUSHVar2POP Var1;Var1中現(xiàn)在的值是原先Var2的值POP Var2;Var2中現(xiàn)在的值是原先Var1的值2. 用于變量之間的數(shù)據(jù)傳遞szStr BYTE10 DUP (0) MOV EAX, 8192 XOR EDX, EDX XOR ECX, ECX MOV EBX, 10a10: DIV EB

4、X ;EDX:EAX除以10 PUSHEDX ;余數(shù)在EDX中, EDX壓棧 INC ECX ;ECX表示壓棧的次數(shù) XOR EDX, EDX ;EDX:EAX=下一次除法的被除數(shù) CMP EAX, EDX ;被除數(shù)=0? JNZa10 ;如果被除數(shù)為0,不再循環(huán) MOV EDI, OFFSET szStra20: POPEAX ;從堆棧中取出商 ADD AL, 0 ;轉(zhuǎn)換為ASCII碼 MOVEDI, AL ;保存在szStr中 INC EDI LOOPa20 ;循環(huán)處理 MOVBYTE PTR EDI, 03. 用做臨時(shí)的數(shù)據(jù)區(qū)例5.1 將EAX中的內(nèi)容轉(zhuǎn)換為十進(jìn)制字符串1.在調(diào)用子程序時(shí)

5、,CALL指令自動(dòng)在堆棧中保存其返回地址;2.從子程序返回時(shí),RET指令從堆棧中取出返回地址。3.子程序中的局部變量也放在堆棧中。子程序執(zhí)行過程中,這些局部變量是可用的;4.主程序還可以將參數(shù)壓入堆棧,子程序從堆棧中取出參數(shù)。4. 子程序的調(diào)用和返回北京理工大學(xué)-張華平-2011145.1.3 子程序的返回地址 例. 段內(nèi)調(diào)用和返回設(shè)計(jì)兩個(gè)子程序:第1個(gè)子程序AddProc1使用ESI和EDI作為加數(shù),做完加法后把和放在EAX中;第2個(gè)子程序AddProc2使用X和Y作為加數(shù),做完加法后把和放在Z中。主程序先后調(diào)用兩個(gè)子程序,最后將結(jié)果顯示出來。在AddProc2中用到了EAX,所以要先將EA

6、X保存在堆棧中,返回時(shí)再恢復(fù)EAX的值。否則EAX中的值會(huì)被破壞。 見程序PROG0501.ASM 。.386.model flat,stdcalloption casemap:noneincludelibmsvcrt.libprintf PROTO C:dword,:vararg.dataszFmt byte %d + %d=%d, 0ah, 0;輸出結(jié)果格式字符串x dword?y dword?z dword?AddProc1 proc ;使用寄存器作為參數(shù) mov eax, esi ;EAX=ESI + EDI add eax, edi retAddProc1 endpAddProc2

7、proc ; 使用變量作為參數(shù) pusheax ; C=A + B mov eax, x add eax, y movz, eax pop eax ;恢復(fù)EAX的值 retAddProc2 endpstart: mov esi, 10 movedi, 20 ;為子程序準(zhǔn)備參數(shù) callAddProc1 ;調(diào)用子程序 ;結(jié)果在EAX中 mov x, 50 mov y, 60 ;為子程序準(zhǔn)備參數(shù) callAddProc2 ;調(diào)用子程序 ;結(jié)果在Z中 invokeprintf, offset szFmt, esi, edi, eax ;顯示第1次加法結(jié)果 invoke printf, offset

8、szFmt, x, y, z ;顯示第2次加法結(jié)果 retend5.2 參數(shù)傳遞可以通過給子程序傳遞參數(shù)使其更通用。常用的參數(shù)傳遞方法如下:1.通過寄存器傳遞;2.通過數(shù)據(jù)區(qū)的變量傳遞3.通過堆棧傳遞北京理工大學(xué)-張華平-2011195.2.1 C語言函數(shù)的參數(shù)傳遞方式 在C/C+以及其他高級(jí)語言中,函數(shù)的參數(shù)是通過堆棧來傳遞的。C語言中的庫函數(shù),以及Windows API等也都使用堆棧方式來傳遞參數(shù)。20C函數(shù)常見的有5種參數(shù)傳遞方式(調(diào)用規(guī)則)見下表。 調(diào)用規(guī)則參數(shù)入棧順序參數(shù)出棧說 明cdecl方式從右至左主程序參數(shù)個(gè)數(shù)可動(dòng)態(tài)變化stdcall方式從右至左子程序Windows API常使

9、用fastcall方式用ECX、EDX傳遞第1、2個(gè)參數(shù),其余的參數(shù)同stdcall,從右至左 子程序常用于內(nèi)核程序this方式ECX等于this,從右至左子程序C+成員函數(shù)使用naked方式從右至左子程序自行編寫進(jìn)入/退出代碼/PROG0502.cint subproc(int a, int b) return a-b;int r,s;int main( )r=subproc(30, 20);s=subproc(r, -1);cdecl方式00401000PUSH EBP00401001 MOV EBP,ESP00401003 MOV EAX,DWORD PTR EBP+800401006S

10、UB EAX,DWORD PTR EBP+0CH00401009 POP EBP0040100A RET0040100B PUSH EBP0040100C MOV EBP,ESP0040100E PUSH 14H00401010 PUSH 1EH00401012 CALL 0040100000401017 ADD ESP,80040101A MOV 00405428,EAX0040101F PUSH 0FFFFFFFFH00401021 MOV EAX,0040542800401026 PUSH EAX00401027 CALL 004010000040102C ADD ESP,8004010

11、2F MOV 0040542C,EAX00401034 POP EBP00401035RETcdecl方式2. stdcall方式堆棧的平衡是由子程序來完成的,子程序使用“RET n”指令Windows API采用的調(diào)用規(guī)則就是stdcall方式。WINBASEAPI int WINAPI lstrcmpA(LPCSTR lpStr1, LPCSTR lpStr2);其中的WINAPI定義為:#define WINAPI _stdcall將subproc( )設(shè)置為使用_stdcall調(diào)用規(guī)則:int _stdcall subproc(int a, int b)stdcall方式3. fast

12、call方式這種方式和stdcall類似。區(qū)別是它使用ECX傳遞第1個(gè)參數(shù),EDX傳遞第2個(gè)參數(shù)。其余的參數(shù)采用從右至左的順序入棧,由子程序在返回時(shí)平衡堆棧。例如:int _fastcall addproc(int a, int b, int c, int d)4. this方式這種方式和stdcall類似,在C+類的成員函數(shù)中使用。它使用ECX傳遞this指針,即指向?qū)ο?。fastcall方式與this方式由編程者自行編寫函數(shù)內(nèi)的所有代碼,可以使用naked調(diào)用規(guī)則。例5.4 使用naked調(diào)用規(guī)則,使編譯器不會(huì)為函數(shù)subproc生成進(jìn)入代碼和退出代碼。/PROG0503.c_declsp

13、ec(naked) int subproc(int a, int b) _asm mov eax, esp+4 _asm sub eax, esp+8 _asm ret前面4種方式中,編譯器自動(dòng)為函數(shù)生成進(jìn)入代碼和退出代碼。進(jìn)入代碼的形式為:00401000 PUSH EBP00401001 MOV EBP, ESP退出代碼的形式為:00401009 POP EBP0040100A RET 8naked方式5.2.2 匯編語言子程序的參數(shù)傳遞方式SubProc1 proc ;使用堆棧傳遞參數(shù) push ebp mov ebp,esp mov eax,dword ptr ebp+8 ;取出第1個(gè)

14、參數(shù) sub eax,dword ptr ebp+12;取出第2個(gè)參數(shù) pop ebp ret SubProc1 endp5.2.2 匯編語言子程序的參數(shù)傳遞方式SubProc2 proc ;使用堆棧傳遞參數(shù) push ebp mov ebp,esp mov eax,dword ptr ebp+8;取出第1個(gè)參數(shù) sub eax,dword ptr ebp+12;取出第2個(gè)參數(shù) pop ebp ret 8 ;平衡主程序的堆棧SubProc2 endp5.2.2 匯編語言子程序的參數(shù)傳遞方式start: push 10 ;第2個(gè)參數(shù)入棧 push 20 ;第1個(gè)參數(shù)入棧 call SubProc

15、1 ;調(diào)用子程序 add esp, 8 push 100 ;第2個(gè)參數(shù)入棧 push 200 ;第1個(gè)參數(shù)入棧 call SubProc2 ;調(diào)用子程序 retend start5.2.2 匯編語言子程序的參數(shù)傳遞方式5.2.3 帶參數(shù)子程序的調(diào)用SubProc1 proc C a:dword, b:dword ; 使用C規(guī)則 mov eax, a ; 取出第1個(gè)參數(shù) sub eax, b ; 取出第2個(gè)參數(shù) ret ; 返回值=a-bSubProc1 endpSubProc2 proc stdcall a:dword, b:dword; 使用stdcall規(guī)則 mov eax, a ; 取出

16、第1個(gè)參數(shù) sub eax, b ; 取出第2個(gè)參數(shù) ret ; 返回值=a-bSubProc2 endpstart: invoke SubProc1, 20, 10 invoke printf, offset szMsgOut, 20, 10, eax invoke SubProc2, 200, 100 invoke printf, offset szMsgOut, 200, 100, eax retendstart5.2.3 帶參數(shù)子程序的調(diào)用invoke SubProc1, r*2, 30局部變量只供子程序內(nèi)部使用,使用局部變量能提高程序的模塊化程度,節(jié)約內(nèi)存空間。局部變量也被稱為自動(dòng)變

17、量。在高級(jí)語言中,局部變量的實(shí)現(xiàn)原理如下。(1)在進(jìn)入子程序的時(shí)候,通過修改堆棧指針ESP來預(yù)留出需要的空間。用SUB ESP, x指令預(yù)留空間,x為該子程序中所有局部變量使用的空間。(2)在返回主程序之前,通過恢復(fù)ESP來釋放這些空間,在堆棧中不再為子程序的局部變量保留空間。5.2.4 子程序中的局部變量LOCAL偽指令的格式為:LOCAL變量名1重復(fù)數(shù)量:類型, 變量名2重復(fù)數(shù)量:類型LOCAL偽指令必須緊接在子程序定義的偽指令PROC之后5.2.4 子程序中的局部變量LOCAL TEMP3:DWORDLOCAL TEMP1, TEMP2:DWORDswap procC a:ptr dwo

18、rd, b:ptr dword;使用堆棧傳遞參數(shù)localtemp1,temp2:dwordmoveax, a movecx, eaxmovtemp1, ecx ;temp1=*amovebx, b movedx, ebxmovtemp2, edx ;temp2=*bmovecx, temp2moveax, amoveax, ecx ;*a=temp2movebx, b movedx, temp1movebx, edx ;*b=temp1retswapendp5.2.4 子程序中的局部變量startprocinvokeprintf, offset szMsgOut, r, sinvokeswa

19、p, offset r, offset s invokeprintf, offset szMsgOut, r, sretstartendpendstart5.2.4 子程序中的局部變量5.3 子程序的特殊應(yīng)用5.3.1、子程序嵌套 在匯編語言中,允許子程序作為調(diào)用程序去調(diào)用另一子程序,把這種關(guān)系稱為子程序嵌套。3層子程序嵌套示意圖。嵌套的層數(shù)沒什么限制,其層數(shù)稱為嵌套深度。主程序SUB1SUB2CALL SUB1CALL SUB2RETRETRET子程序嵌套示意圖返回 由于子程序嵌套對(duì)堆棧的使用很頻繁,因此還要確保堆棧有足夠空間,并要注意堆棧的正確狀態(tài),這包括CALL、RET、RET N、PU

20、SH、POP、INT、IRET等與堆棧操作有關(guān)指令的正確使用。5.3 子程序的特殊應(yīng)用5.3.2、子程序遞歸factorial proc C n:dword cmp n, 1 jbe exitrecurse mov ebx, n ;EBX=n dec ebx ;EBX=n-1 invokefactorial, ebx ;EAX=(n-1)! imul n ;EAX=EAX * n ret ;=(n-1)! * n=n!exitrecurse: mov eax, 1 ;n=1時(shí), n!=1 retfactorial endpstart proc local n,f:dword mov n, 5

21、invoke factorial,n;EAX=n! mov f, eax invoke printf, offset szOut, n, f ret北京理工大學(xué)-張華平-20115.3.3 緩沖區(qū)溢出緩沖區(qū)溢出是目前最常見的一種安全問題,操作系統(tǒng)以及應(yīng)用程序一般都存在緩沖區(qū)溢出漏洞。緩沖區(qū)溢出是由編程錯(cuò)誤引起的,當(dāng)程序向緩沖區(qū)內(nèi)寫入的數(shù)據(jù)超過了緩沖區(qū)的容量,就發(fā)生了緩沖區(qū)溢出,緩沖區(qū)之外的內(nèi)存單元被程序“非法”修改。一般情況下,緩沖區(qū)溢出會(huì)導(dǎo)致應(yīng)用程序的錯(cuò)誤或者運(yùn)行中止,但是,攻擊者利用程序中的漏洞,精心設(shè)計(jì)出一段入侵程序代碼,覆蓋緩沖區(qū)之外的內(nèi)存單元,這些程序代碼就可以被CPU所執(zhí)行,從而獲

22、取系統(tǒng)的控制權(quán)。 北京理工大學(xué)-張華平-2011411 堆棧溢出 在一個(gè)程序中,會(huì)聲明各種變量。靜態(tài)全局變量位于數(shù)據(jù)段并且在程序開始運(yùn)行時(shí)被初始化,而局部變量則在堆棧中分配,只在該函數(shù)內(nèi)部有效。 如果局部變量使用不當(dāng),會(huì)造成緩沖區(qū)溢出漏洞。int main(int argc, char *argv)char buf 80;strcpy(buf, argv1); 北京理工大學(xué)-張華平-2011432 數(shù)據(jù)區(qū)溢出 當(dāng)變量或數(shù)組位于數(shù)據(jù)區(qū)時(shí),由于程序?qū)ψ兞俊?shù)組的過度使用而導(dǎo)致對(duì)其他數(shù)據(jù)單元的覆蓋,也可能導(dǎo)致程序執(zhí)行錯(cuò)誤。;PROG0508.asm.386.model flat,stdcallinc

23、ludelib msvcrt.libprintf PROTO C:dword,:varargscanf PROTO C:dword,:vararg.dataszMsg byte f is called. buf=%s, 0ah, 0szFormat byte %s, 0buf byte 40 dup (0)fn dwordoffset f.codef proc invoke printf, offset szMsg, offset buf retf endpstart: invoke scanf, offset szFormat, offset buf call dword ptr fninv

24、alidarg: retend start當(dāng)輸入的字符長(zhǎng)度超過40個(gè)字節(jié)以后,后面的fn就被覆蓋。執(zhí)行“call dword ptr fn”指令時(shí),從fn單元中取出的內(nèi)容就不再是子程序f的地址北京理工大學(xué)-張華平-2011455.4 模塊化程序設(shè)計(jì) 如果有多個(gè)源程序文件,或者需要使用C/C+、匯編等多種語言混合編程,就需要對(duì)這些源程序分別編譯,最后連接構(gòu)成一個(gè)可執(zhí)行文件。 北京理工大學(xué)-張華平-201146如圖所示,系統(tǒng)由模塊A、模塊B、模塊C組成,而模塊B中的部分功能又可以進(jìn)一步分解成為模塊D、模塊E,整個(gè)系統(tǒng)包括了5個(gè)模塊。模塊中的代碼設(shè)計(jì)為子程序,能夠相互進(jìn)行調(diào)用。 北京理工大學(xué)-張華平

25、-201147在子程序設(shè)計(jì)中,主程序和子程序之間可以通過全局變量、寄存器、堆棧等方式傳遞數(shù)據(jù),這種技術(shù)在模塊化程序設(shè)計(jì)中同樣適用。 北京理工大學(xué)-張華平-2011485.4.2 模塊間的通信 由于各個(gè)模塊需要單獨(dú)匯編,于是就會(huì)出現(xiàn)當(dāng)一個(gè)模塊通過名字調(diào)用另一模塊中的子程序或使用其數(shù)據(jù)時(shí),這些名字對(duì)于調(diào)用者來講是未定義的,因此在匯編過程中就會(huì)出現(xiàn)符號(hào)未定義錯(cuò)誤??梢酝ㄟ^偽指令EXTRN、PUBLIC等來解決。 北京理工大學(xué)-張華平-2011491. 外部引用偽指令EXTRN格式:EXTRN 變量名:類型,功能:說明在本模塊中用到的變量是在另一個(gè)模塊中定義的,同時(shí)指出變量的類型。 北京理工大學(xué)-張華

26、平-2011502. 全局符號(hào)說明偽指令PUBLIC格式:PUBLIC 名字,功能:告訴匯編程序本模塊中定義的名字可以被其他模塊使用。這里的名字可以是變量名,也可以是子程序名。 3. 子程序聲明偽指令PROTO格式:子程序名 PROTO C | stdcall :第一個(gè)參數(shù)類型 ,:后續(xù)參數(shù)類型功能:說明子程序的名字和參數(shù)類型,供主程序調(diào)用。在前面的程序中,已經(jīng)多次使用這種方式調(diào)用C語言的庫函數(shù)及Windows的API。 ;PROG0509.asm.386.model flat,stdcalloption casemap:noneincludelib msvcrt.libprintf PROT

27、O C :dword,:varargSubProc PROTO stdcall :dword, :dword ; SubProc位于其他模塊中public result ;允許其他模塊使用result.dataszOutputFmtStrbyte %d?%d=%d, 0ah, 0 ;輸出結(jié)果oprd1 dword 70 ;被減數(shù)oprd2 dword 40 ;減數(shù)result dword ? ;差.codemain proc C argc, argvinvoke SubProc, oprd1, oprd2 ;調(diào)用其他模塊中的函數(shù) invoke printf, offset szOutputFm

28、tStr, ;輸出結(jié)果 oprd1, oprd2, result ;result由SubProc設(shè)置 retmain endpend;PROG0510.asm.386.model flat,stdcallpublic SubProc ;允許其他模塊調(diào)用SubProcextrn result:dword;result位于其他模塊中.data.codeSubProc proc stdcall a, b ;減法函數(shù), stdcall調(diào)用方式 mov eax, a ;參數(shù)為a,b sub eax, b ;EAX=a-b mov result, eax ;減法的結(jié)果保存在result中 ret 8 ;返

29、回a-bSubProc endpendPROG0509.ASMPROG0510.ASMPROG0509.OBJPROG0509.OBJPROG0510 x.exe編譯鏈接ml /c /coff prog0509.asmml /c /coff prog0510.asmlink prog0509.obj prog0510.obj /out:prog0510 x.exe /subsystem:console5.5 C語言模塊的反匯編匯編語言的一個(gè)重要應(yīng)用就是程序的底層分析,學(xué)會(huì)閱讀反匯編程序,通過逆向分析將反匯編程序?qū)懗筛呒?jí)語言如C語言等代碼格式,在實(shí)際工程應(yīng)用中具有重要意義。對(duì)高級(jí)語言底層實(shí)現(xiàn)細(xì)節(jié)

30、的分析,能夠了解程序的實(shí)現(xiàn)機(jī)理,對(duì)編寫高效率的程序也有很大幫助。 5.5.1 基本框架/PROG0511.c1:#include stdio.h2:int main( )3:4:return 0;5:0040102055pushebp004010218B ECmovebp,esp0040102383 EC 40subesp,40h0040102653pushebx0040102756pushesi0040102857pushedi004010298D 7D C0leaedi,ebp-40h0040102CB9 10 00 00 00movecx,10h00401031B8 CC CC CC C

31、Cmoveax,0CCCCCCCCh00401036F3 ABrep stos dword ptr edi;以上為棧初始化過程。0040103833 C0 xoreax,eax; 返回值0保存在eax中。0040103A5Fpopedi0040103B5Epopesi0040103C5Bpopebx0040103D8B E5movesp,ebp0040103F5Dpopebp;以上為棧初恢復(fù)過程。00401040C3ret5.5.1 基本框架5.5.2 選擇結(jié)構(gòu)1:int i;2:if(i=0)3:printf(i is nonnegative!);4:else5:printf(i is ne

32、gative!);0040104983 7D FC 00cmpdword ptr ebp-4,00040104D7C 0Fjlmain+3Eh (0040105e)0040104F68 84 0F 42 00pushoffset string i is nonnegative! (00420f84)00401054E8 87 00 00 00callprintf (004010e0)0040105983 C4 04addesp,40040105CEB 0Djmpmain+4Bh (0040106b)0040105E68 74 0F 42 00pushoffset string i is neg

33、ative! (00420f74)00401063E8 78 00 00 00callprintf (004010e0)0040106883 C4 04addesp,45.5.3 循環(huán)結(jié)構(gòu)1:int i;2:for(i=1;i=10;i+)3:;00401038C7 45 FC 01 00 00 00movdword ptr ebp-4,1;局部變量i保存在棧中,通過ebp-4的方式訪問。0040103FEB 09jmpmain+2Ah (0040104a)004010418B 45 FCmoveax,dword ptr ebp-40040104483 C0 01addeax,10040104

34、789 45 FCmovdword ptr ebp-4,eax0040104A83 7D FC 0Acmpdword ptr ebp-4,0Ah0040104E7F 02jgmain+32h (00401052)00401050EB EF jmpmain+21h (00401041)5.5.4 變量定義/PROG0512.c1:#include stdio.h2:int i1;/全局變量3:static int i2;/靜態(tài)全局變量4:int main( )5:6:int i3;/局部變量7:i1=0;8:i2=0;9:i3=0;10:return 1;11:00401028C7 05 B8

35、27 42 00 00movdword ptr _i1 (004227b8),0;全局變量i100401032C7 05 D8 25 42 00 00movdword ptr i2 (004225d8),0;靜態(tài)變量i20040103CC7 45 FC 00 00 00 00movdword ptr ebp-4,0;局部變量i300401043B8 01 00 00 00moveax,1;返回值保存在eax0040104EC3ret5.5.5 指針/PROG0513.c1:#include stdio.h2:int main( )3:4:int *p,a; 5:a=10;6:p=&a;7:反匯

36、編碼如下所示。00401028C7 45 F8 0A 00 00 00movdword ptr ebp-8,0Ah;a=10,a為局部變量,通過ebp-n的方式訪問。0040102F8D 45 F8leaeax,ebp-80040103289 45 FCmovdword ptr ebp-4,eax; p=&a,p為局部變量,p中保存著a的地址。5.5.6 函數(shù)/PROG0514.c1:#include stdio.h2:int subproc(int a, int b)3:4: return a*b;5:子程序subproc的反匯編碼如下所示。;以上為棧的初始化略004010288B 45 0

37、8 moveax,dword ptr ebp+80040102B0F AF 45 0C imuleax,dword ptr ebp+0Ch;eax = a*b;返回值保存在eax中;以上為棧的恢復(fù),略00401035C3ret5.5.6 函數(shù)6:int main( )7:8: int r,s;9: r=subproc(10, 8);10: s=subproc(r, -1);11:printf(r=%d,s=%d,r,s);12:主程序main反匯編碼如下所示。00401005E9 66 A4 00 00jmpmain (0040b470)0040100AE9 01 00 00 00jmpsub

38、proc (00401010)棧初始化(略)0040B4886A 08push80040B48A6A 0Apush0Ah0040B48CE8 79 5B FF FFcallILT+5(_subproc) (0040100a)0040B49183 C4 08addesp,8;第一次函數(shù)調(diào)用0040B49489 45 FCmovdword ptr ebp-4,eax0040B4976A FFpush0FFh0040B4998B 45 FCmoveax,dword ptr ebp-40040B49C50pusheax0040B49DE8 68 5B FF FFcallILT+5(_subproc)

39、(0040100a)0040B4A283 C4 08addesp,8;第二次函數(shù)調(diào)用0040B4A589 45 F8movdword ptr ebp-8,eax0040B4A88B 4D F8movecx,dword ptr ebp-80040B4AB51pushecx0040B4AC8B 55 FCmovedx,dword ptr ebp-40040B4AF52pushedx0040B4B068 50 FE 41 00pushoffset string r=%d,s=%d (0041fe50)0040B4B5E8 76 02 00 00callprintf (0040b730)0040B4B

40、A83 C4 0Caddesp,0Ch;輸出結(jié)果11:printf(r=%d,s=%d,r,s);5.5.6 函數(shù)在C程序中直接嵌入?yún)R編代碼,或者由C語言主程序調(diào)用匯編子程序。5.6 C語言和匯編語言的混合編程要求執(zhí)行速度快、占用空間小、要求直接控制硬件等場(chǎng)合,仍然要用到匯編語言程序,在這種情況下,使用匯編語言編程是程序設(shè)計(jì)人員的最好選擇5.6.1 直接嵌入其格式為:_asm 匯編語句對(duì)于連續(xù)的多個(gè)匯編語句,可以采用下面的形式:_asm 匯編語句 匯編語句 內(nèi)嵌匯編語句的操作碼必須是有效的80 x86指令。不能使用BYTE、WORD、DWORD等語句定義數(shù)據(jù)。5.6.2 C程序調(diào)用匯編子程序C

41、變量類型匯編變量類型大小CharSBYTE1字節(jié)shortSWORD2字節(jié)intSDWORD4字節(jié)longSDWORD4字節(jié)unsigned charBYTE1字節(jié)unsigned shortWORD2字節(jié)unsigned intDWORD4字節(jié)unsigned longDWORD4字節(jié)指針DWORD4字節(jié)在匯編模塊中,用PUBLIC語句允許外部模塊來訪問這些變量。例如:public _a, _b_a sdword 3_b sdword 4extern int a, b;1.C模塊使用匯編模塊中的變量5.6.2 C程序調(diào)用匯編子程序2. 匯編模塊使用C模塊中的變量在C模塊中應(yīng)該用extern來

42、指明這些變量可以由外部模塊所使用。例如:extern int z;int z;在匯編模塊中,要使用這些變量,需要EXTRN加以說明。之后,在匯編模塊中就可以訪問C模塊中的變量了。即:extrn_z:sdwordmov _z, esi5.6.2 C程序調(diào)用匯編子程序3. C模塊調(diào)用匯編模塊中的子程序匯編模塊中的語句以子程序的形式編寫,相當(dāng)于C語言的一個(gè)函數(shù)。在C模塊中,使用extern表明這個(gè)函數(shù)來自于外部模塊,同時(shí)說明它的參數(shù)類型及返回值類型,例如:extern int CalcAXBY(int x, int y);之后,就可以在C模塊中調(diào)用匯編模塊中的子程序:int r=CalcAXBY(x, y);CalcAXBY函數(shù)把返回值存入EAX中。5.6.2 C程序調(diào)用匯編子程序/PROG0515.c#include stdio.hextern int a, b; extern int CalcAXBY(int x, int y);extern int z;int z;int x=10, y=20;int main()int r=CalcAXBY(x, y);printf(%d*%d+%d*%

溫馨提示

  • 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ì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論