版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
匯編與接口技術(shù)
第五章子程序設(shè)計(jì)子程序定義使用過程定義偽指令PROC定義子程序子程序名 PROC [類型]
…… RET子程序名 ENDP在Win32匯編語言中,PROC后面還可以跟其他參數(shù)子程序一定要在代碼段中定義,在子程序結(jié)束時(shí),要用RET指令返回主程序。使用CALL指令來調(diào)用子程序,其中子程序名可以通過直接或間接方法給出與子程序類型相對應(yīng),CALL指令分為有段內(nèi)和段間調(diào)用主程序和子程序可以在同一個(gè)代碼段也可以在不同代碼段。由于32位匯編程序的內(nèi)存模式為FLAT,一個(gè)段長可達(dá)4GB,所以本節(jié)主要討論段內(nèi)調(diào)用。如果設(shè)計(jì)實(shí)模式程序,則應(yīng)注意一個(gè)段長不能超過64KB設(shè)計(jì)子程序時(shí)應(yīng)注意的問題1.寄存器的保存與恢復(fù)2.保持堆棧平衡3.子程序說明堆棧的用途16位程序中以字為單位進(jìn)行,32位程序中以雙字為單位進(jìn)行(1)保護(hù)和恢復(fù)調(diào)用現(xiàn)場。PUSH EAXPUSH EBX……POP EBXPOP EAX(2)用于變量之間的數(shù)據(jù)傳遞PUSH Var1POP Var2交換兩個(gè)變量Var1和Var2的值。PUSH Var1PUSH Var2POP Var1 ;Var1中現(xiàn)在的值是原先Var2的值POP Var2 ;Var2中現(xiàn)在的值是原先Var1的值(3)用做臨時(shí)的數(shù)據(jù)區(qū)PUSHCount……POPCount將EAX中的內(nèi)容轉(zhuǎn)換為十進(jìn)制字符串對這個(gè)數(shù)連續(xù)除以10,直到所得的商為0結(jié)束。每次除法得到的商加上‘0’就可以轉(zhuǎn)換為ASCII字符。第1次除法所得的余數(shù)是最低位,應(yīng)該放在最后面,作為字符串的最后一個(gè)字符;最后1次除法所得的余數(shù)是最高位,應(yīng)該作為字符串的第一個(gè)字符。szStr
BYTE 10DUP(0)MOV EAX,8192XOR EDX,EDXXOR ECX,ECXMOV EBX,10a10:DIV EBX ;EDX:EAX除以10PUSH EDX ;余數(shù)在EDX中,EDX壓棧INC ECX ;ECX表示壓棧的次數(shù)XOR EDX,EDX;EDX:EAX=下一次除法的被除數(shù)CMP EAX,EDX;被除數(shù)=0?JNZ a10 ;如果被除數(shù)為0,不再循環(huán)MOV EDI,OFFSETszStra20:POP EAX ;從堆棧中取出商ADD AL,'0' ;轉(zhuǎn)換為ASCII碼MOV [EDI],AL ;保存在szStr中INC EDILOOP a20 ;循環(huán)處理MOV BYTEPTR[EDI],0返回地址作為一個(gè)雙字壓棧設(shè)計(jì)兩個(gè)子程序:第1個(gè)子程序AddProc1使用ESI和EDI作為加數(shù),做完加法后把和放在EAX中;第2個(gè)子程序AddProc2使用X和Y作為加數(shù),做完加法后把和放在Z中。主程序先后調(diào)用兩個(gè)子程序,最后將結(jié)果顯示出來。.386.modelflat,stdcalloptioncasemap:noneincludelib msvcrt.libprintf PROTOC :dword,:vararg.dataszFmt byte '%d+%d=%d',0ah,0 ;輸出結(jié)果格式字符串x dword ?y dword ?z dword ?.codeAddProc1 proc ;使用寄存器作為參數(shù) mov eax,esi ;EAX=ESI+EDI add eax,edi retAddProc1 endpAddProc2 proc ;使用變量作為參數(shù) push eax ;C=A+B mov eax,x add eax,y mov z,eax pop eax ;恢復(fù)EAX的值 retAddProc2 endpstart: mov esi,10 mov edi,20 ;為子程序準(zhǔn)備參數(shù) call AddProc1 ;調(diào)用子程序 ;結(jié)果在EAX中 mov x,50 mov y,60 ;為子程序準(zhǔn)備參數(shù) call AddProc2 ;調(diào)用子程序 ;結(jié)果在Z中 invoke printf,offsetszFmt, esi,edi,eax ;顯示第1次加法結(jié)果 invoke printf,offsetszFmt, x,y,z ;顯示第2次加法結(jié)果 retend start參數(shù)傳遞在主程序和子程序中傳遞參數(shù),通常有3種方法:通過寄存器傳遞、通過數(shù)據(jù)區(qū)的變量傳遞、通過堆棧傳遞。在C/C++以及其他高級語言中,函數(shù)的參數(shù)是通過堆棧來傳遞的。C語言中的庫函數(shù),以及WindowsAPI等也都使用堆棧方式來傳遞參數(shù)。例如:MessageBox就屬于WindowsAPI函數(shù),而printf、scanf屬于C的庫函數(shù)。C函數(shù)常見的有5種參數(shù)傳遞方式cdecl方式cdecl方式是C函數(shù)的默認(rèn)方式,不加說明時(shí),函數(shù)就使用cdecl調(diào)用規(guī)則。設(shè)計(jì)一個(gè)通過堆棧傳遞函數(shù)參數(shù)的C程序。函數(shù)subproc()有兩個(gè)整型參數(shù),參數(shù)名為a和b。函數(shù)的功能是計(jì)算a-b,減法的結(jié)果作為函數(shù)的返回值。cdecl方式(1)使用堆棧傳遞參數(shù)。(2)主程序按從右向左的順序?qū)?shù)逐個(gè)壓棧。最后一個(gè)參數(shù)先入棧。每一個(gè)參數(shù)壓棧一次,在堆棧中占4字節(jié)。(3)在子程序中,使用[EBP+X]的方式來訪問參數(shù)。X=8代表第1個(gè)參數(shù);X=12代表第2個(gè)參數(shù),依次類推。(4)子程序用RET指令返回。(5)由主程序執(zhí)行“ADDESP,N”指令調(diào)整ESP,達(dá)到堆棧平衡。N等于參數(shù)個(gè)數(shù)乘以4。每個(gè)參數(shù)在堆棧中占4字節(jié)。(6)子程序的返回值放在EAX中。C程序intsubproc(inta,intb){ returna-b;}intr,s;intmain(){ r=subproc(30,20); s=subproc(r,-1);}編譯后的機(jī)器指令。subproc函數(shù)的地址為00401000H,main函數(shù)的地址為0040100BH。主程序在調(diào)用subproc函數(shù)前,將20、30壓棧。子程序通過[EBP+8]取得堆棧中的參數(shù)a,通過[EBP+0CH]取得堆棧中的參數(shù)b。子程序返回主程序后,主程序執(zhí)行“ADDESP,8”,意味著30、20出棧。00401000 PUSH EBP00401001 MOV EBP,ESP00401003MOV EAX,DWORDPTR[EBP+8]00401006 SUB EAX,DWORDPTR[EBP+0CH]00401009 POP EBP0040100A RET0040100B PUSH EBP0040100C MOV EBP,ESP0040100E PUSH 14H00401010PUSH 1EH00401012 CALL 0040100000401017ADD ESP,80040101AMOV [00405428],EAX0040101FPUSH 0FFFFFFFFH00401021 MOV EAX,[00405428]00401026PUSH EAX00401027CALL 004010000040102CADD ESP,80040102FMOV [0040542C],EAX00401034POP EBP00401035 RETstdcall方式stdcall方式的調(diào)用規(guī)則也是使用堆棧傳遞參數(shù),使用從右向左的順序?qū)?shù)入棧。與cdecl方式不同的是,堆棧的平衡是由子程序來完成的。子程序使用“RETn”指令,在返回主程序的同時(shí)平衡ESP。子程序的返回值放在EAX中。WindowsAPI采用的調(diào)用規(guī)則就是stdcall方式int__stdcallsubproc(inta,intb) //兩個(gè)下劃線{ returna-b;}intr,s;intmain(){ r=subproc(30,20); s=subproc(r,-1);}fastcall方式這種方式和stdcall類似。區(qū)別是它使用ECX傳遞第1個(gè)參數(shù),EDX傳遞第2個(gè)參數(shù)。其余的參數(shù)采用從右至左的順序入棧,由子程序在返回時(shí)平衡堆棧。例如:int_fastcalladdproc(inta,intb,intc,intd)this方式這種方式和stdcall類似,在C++類的成員函數(shù)中使用。它使用ECX傳遞this指針。naked方式前面4種方式中,編譯器自動(dòng)為函數(shù)生成進(jìn)入代碼和退出代碼。進(jìn)入代碼的形式為:00401000PUSH EBP00401001MOV EBP,ESP退出代碼的形式為:00401009POP EBP0040100ARET 8如果不想讓編譯器生成這些進(jìn)入代碼和退出代碼,而是要由編程者自行編寫函數(shù)內(nèi)的所有代碼。這時(shí),就可以使用naked調(diào)用規(guī)則。匯編語言子程序的參數(shù)傳遞方式匯編語言中,向子程序傳遞參數(shù)可以仿照C程序的方式來處理子程序參數(shù)傳遞SubProc1采用cdecl方式,而SubProc2采用stdcall方式.386.modelflat,stdcall.data.codeSubProc1proc ;使用堆棧傳遞參數(shù)push ebpmov ebp,espmov eax,dwordptr[ebp+8] ;取出第1個(gè)參數(shù)subeax,dwordptr[ebp+12] ;取出第2個(gè)參數(shù)popebp ret SubProc1endpSubProc2proc ;使用堆棧傳遞參數(shù)push ebpmov ebp,espmov eax,dwordptr[ebp+8] ;取出第1個(gè)參數(shù)sub eax,dwordptr[ebp+12] ;取出第2個(gè)參數(shù)pop ebp ret 8 ;平衡主程序的堆棧SubProc2endpstart:push 10 ;第2個(gè)參數(shù)入棧push 20 ;第1個(gè)參數(shù)入棧call SubProc1 ;調(diào)用子程序add esp,8push 100 ;第2個(gè)參數(shù)入棧push 200 ;第1個(gè)參數(shù)入棧call SubProc2 ;調(diào)用子程序retendstart分析在調(diào)用“SubProc1”之前,主程序?qū)?0、20壓入堆棧;執(zhí)行“callSubProc1”之后,返回地址被壓入堆棧;執(zhí)行“pushebp”、“movebp,esp”之后,EBP被壓入堆棧。此時(shí),[EBP+8]的內(nèi)容為20,即子程序的第1個(gè)參數(shù),[EBP+12]的內(nèi)容為10,是子程序的第2個(gè)參數(shù)。帶參數(shù)子程序的調(diào)用MASM提供了一個(gè)偽指令I(lǐng)NVOKE來簡化子程序的設(shè)計(jì)和調(diào)用。在定義子程序時(shí),可以說明是使用cdecl規(guī)則還是stdcall規(guī)則,并指出各參數(shù)的名稱。在調(diào)用子程序時(shí),使用INVOKE偽指令,后面跟子程序名和各個(gè)參數(shù)即可,由編譯軟件在編譯時(shí)完成將參數(shù)轉(zhuǎn)換為[EBP+x]等工作。重新前面的程序:定義SubProc1時(shí),后面跟“C”,表示它使用cdecl調(diào)用規(guī)則(C語言默認(rèn)的規(guī)則)。定義SubProc2時(shí),后面跟“stdcall”,表示它使用stdcall調(diào)用規(guī)則。調(diào)用規(guī)則后面直接跟參數(shù)的名字和類型。子程序中,不需要使用[EBP+8]、[EBP+12]等形式來指定參數(shù),而直接使用a、b等形式參數(shù)即可。MASM自動(dòng)地將a替換為[EBP+8],將b替換為[EBP+12]。子程序開始的地方也不再需要“PUSHEBP”、“MOVEBP,ESP”指令,結(jié)束時(shí)也不需要“POPEBP”指令。編譯時(shí),MASM自動(dòng)在子程序開始的地方插入“PUSHEBP”、“MOVEBP,ESP”指令如果使用了stdcall調(diào)用規(guī)則,MASM自動(dòng)將“RET”指令替換為“RETn”指令。n等于參數(shù)個(gè)數(shù)乘以4。.386.modelflat,stdcallincludelibmsvcrt.libprintf
PROTOC:dword,:vararg.dataszMsgOut
byte '%d-%d=%d',0ah,0.codeSubProc1 proc Ca:dword,b:dword ;使用C規(guī)則 mov eax,a ;取出第1個(gè)參數(shù) sub eax,b ;取出第2個(gè)參數(shù) ret ;返回值=a-bSubProc1 endpSubProc2 proc stdcalla:dword,b:dword ;使用stdcall規(guī)則 mov eax,a ;取出第1個(gè)參數(shù) sub eax,b ;取出第2個(gè)參數(shù) ret ;返回值=a-bSubProc2 endpstart: invoke SubProc1,20,10 invoke printf,offsetszMsgOut,20,10,eax
invoke SubProc2,200,100 invoke printf,offsetszMsgOut,200,100,eax retend start注意在子程序中不能隨意改變EBP的值,因?yàn)樽映绦蛞揽縀BP來訪問位于堆棧中的參數(shù)。invoke偽指令后面跟的參數(shù)不能像C語言那樣靈活。在C語言中,參數(shù)本身可以是一個(gè)表達(dá)式,例如SubProc1(r*2,30)。在匯編語言中,invoke偽指令后面跟的參數(shù)必須直接能夠作為PUSH指令的源操作數(shù),因此,下面這樣的指令是不符合規(guī)則的,編譯時(shí)會(huì)報(bào)錯(cuò):invokeSubProc1,r*2,30子程序中的局部變量局部變量只供子程序內(nèi)部使用,使用局部變量能提高程序的模塊化程度,節(jié)約內(nèi)存空間。局部變量也被稱為自動(dòng)變量。在高級語言中,局部變量的實(shí)現(xiàn)原理如下。(1)在進(jìn)入子程序的時(shí)候,通過修改堆棧指針ESP來預(yù)留出需要的空間。用SUBESP,x指令預(yù)留空間,x為該子程序中所有局部變量使用的空間。(2)在返回主程序之前,通過恢復(fù)ESP來釋放這些空間,在堆棧中不再為子程序的局部變量保留空間。MASM提供了LOCAL偽指令,可以在子程序中方便地定義局部變量。LOCAL變量名1[重復(fù)數(shù)量][:類型],變量名2[重復(fù)數(shù)量][:類型]……LOCAL偽指令必須緊接在子程序定義的偽指令PROC之后,可以使用多個(gè)LOCAL語句。變量類型可以是BYTE、WORD、DWORD等。還可以定義一個(gè)局部的結(jié)構(gòu)變量,此時(shí)可以用結(jié)構(gòu)的名稱當(dāng)作類型。在子程序中還可以定義一個(gè)局部數(shù)組LOCALTEMP[3]:DWORDTEMP數(shù)組有3個(gè)元素。每個(gè)元素占4字節(jié),TEMP數(shù)組在堆棧中占12字節(jié)。在程序中使用TEMP[0]代表第0個(gè)元素,TEMP[4]代表第1個(gè)元素,TEMP[8]代表第2個(gè)元素。如果在子程序中定義了局部變量,而在INVOKE語句中使用這個(gè)局部變量的地址,就需要用到ADDR偽操作符,而不能使用OFFSET偽操作符。OFFSET后面只能跟全局變量(即在數(shù)據(jù)區(qū)中定義的變量)和程序中的標(biāo)號,不能跟局部變量。LOCALTEMP1,TEMP2:DWORDMASM將TEMP1作為[EBP-4],將TEMP2作為[EBP-8]。但子程序中直接使用TEMP1、TEMP2,而不必使用[EBP-4]、[EBP-8]的形式。SWAP的兩個(gè)入口參數(shù)a和b是兩個(gè)指針,所以a和b的類型用“PTRDWORD”說明。.386.modelflat,stdcallincludelib msvcrt.libprintf PROTOc
:dword,:vararg.datar dword10s dword20szMsgOut byte 'r=%ds=%d',0ah,0.codeswap proc Ca:ptrdword,b:ptrdword ;使用堆棧傳遞參數(shù) local temp1,temp2:dword mov eax,a mov ecx,[eax] mov temp1,ecx ;temp1=*a mov ebx,b mov edx,[ebx] mov temp2,edx ;temp2=*b mov ecx,temp2 mov eax,a mov [eax],ecx ;*a=temp2 mov ebx,b mov edx,temp1 mov [ebx],edx ;*b=temp1 retswap endpstart proc invoke printf,offsetszMsgOut,r,s invoke swap,offsetr,offsets invoke printf,offsetszMsgOut,r,s retstart endpend start子程序嵌套(不舉例)子程序遞歸計(jì)算n!(n的階乘)n!=n×(n-1)! (若n>1)n!=1 (若n=0,1)分析:子程序factorial將n作為參數(shù),結(jié)果n!放置在EAX中。子程序中首先判斷n是否小于等于1,若是,返回1即可;否則調(diào)用它自己求出(n-1)!,調(diào)用它自身時(shí),以n-1作為子程序的參數(shù),求出(n-1)!后,再將它乘以n放置在EAX中,作為子程序的返回值。.386.modelflat,stdcallincludelib
msvcrt.libprintfPROTOC:dword,:vararg.dataszOutbyte 'n=%d(n!)=%d',0AH,0.codefactorial proc Cn:dword cmp n,1 jbe exitrecurse mov ebx,n ;EBX=n dec ebx ;EBX=n-1 invoke factorial,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 invoke factorial,n ;EAX=n! mov f,eax invoke printf,offsetszOut,n,f retstart endpend start緩沖區(qū)溢出緩沖區(qū)溢出是由編程錯(cuò)誤引起的,當(dāng)程序向緩沖區(qū)內(nèi)寫入的數(shù)據(jù)超過了緩沖區(qū)的容量,就發(fā)生了緩沖區(qū)溢出,緩沖區(qū)之外的內(nèi)存單元被程序“非法”修改。攻擊者利用程序中的漏洞,精心設(shè)計(jì)出一段入侵程序代碼,覆蓋緩沖區(qū)之外的內(nèi)存單元,這些程序代碼就可以被CPU所執(zhí)行,從而獲取系統(tǒng)的控制權(quán)。模塊化程序設(shè)計(jì)有多個(gè)源程序文件,或者需要使用C/C++、匯編等多種語言混合編程,就需要對這些源程序分別編譯,最后連接構(gòu)成一個(gè)可執(zhí)行文件。通過對系統(tǒng)功能的分析,采取“分而治之”的辦法,將一個(gè)大的系統(tǒng)分解為小的模塊,每一個(gè)模塊都可以采取不同的編程語言。各個(gè)模塊的開發(fā)可以由多個(gè)開發(fā)人員并行完成,最后,將所有模塊組合成為一個(gè)完整的系統(tǒng)。模塊間的通信由于各個(gè)模塊需要單獨(dú)匯編,于是就會(huì)出現(xiàn)當(dāng)一個(gè)模塊通過名字調(diào)用另一模塊中的子程序或使用其數(shù)據(jù)時(shí),這些名字對于調(diào)用者來講是未定義的,因此在匯編過程中就會(huì)出現(xiàn)符號未定義錯(cuò)誤??梢酝ㄟ^偽指令EXTRN、PUBLIC等來解決。外部引用偽指令格式:EXTRN/EXTERN變量名:類型[,…]功能:說明在本模塊中用到的變量是在另一個(gè)模塊中定義的,同時(shí)指出變量的類型。說明:這里的名字一般是變量名,變量是在另一模塊中定義的。類型可以是BYTE、WORD、DWORD,與另一模塊對該變量的定義要一致。EXTRN偽指令應(yīng)該出現(xiàn)在程序引用該名字之前,一般放在程序的開頭。全局符號說明偽指令格式:PUBLIC名字[,…]功能:告訴匯編程序本模塊中定義的名字可以被其他模塊使用。這里的名字可以是變量名,也可以是子程序名。子程序聲明偽指令格式:子程序名PROTO[C|stdcall]:[第一個(gè)參數(shù)類型][,:后續(xù)參數(shù)類型]功能:說明子程序的名字和參數(shù)類型,供主程序調(diào)用。在模塊化程序設(shè)計(jì)中,若子程序位于另一模塊,則在主程序模塊中,就需要用PROTO偽指令對子程序的名字、調(diào)用方式和參數(shù)類型予以說明。設(shè)計(jì)由兩個(gè)模塊組成的程序,模塊名分別為PROG0509.ASM和PROG0510.ASM。其中主模塊調(diào)用子模塊中的SubProc子程序?qū)崿F(xiàn)減法功能。;PROG0509.asm.386.model flat,stdcalloption casemap:noneincludelib msvcrt.libprintf PROTOC:dword,:varargSubProcPROTOstdcall:dword,:dword ;SubProc位于其他模塊中public result ;允許其他模塊使用result.dataszOutputFmtStr byte '%d-%d=%d',0ah,0 ;輸出結(jié)果oprd1 dword 70 ;被減數(shù)oprd2 dword 40 ;減數(shù)result dword ? ;差.codemain proc Cargc,argv invoke SubProc,oprd1,oprd2 ;調(diào)用其他模塊中的函數(shù) invoke printf,offsetszOutputFmtStr,\ ;輸出結(jié)果 oprd1,\ oprd2,\ result ;result由SubProc設(shè)置 retmain endp end;PROG0510.asm.386.modelflat,stdcallpublic SubProc ;允許其他模塊調(diào)用SubProcextrn result:dword ;result位于其他模塊中.data.codeSubProc proc stdcalla,b ;減法函數(shù),stdcall調(diào)用方式 mov eax,a ;參數(shù)為a,b sub eax,b ;EAX=a-b mov result,eax ;減法的結(jié)果保存在result中 ret 8 ;返回a-bSubProc endp end使用ML分別編譯模塊PROG0509.ASM和PROG0510.ASM,分別得到PROG0509.OBJ和PROG0510.OBJ。最后,再使用LINK將兩個(gè).OBJ文件連接生成一個(gè).EXE文件,使用/out選項(xiàng)來指定產(chǎn)生的.EXE文件名。PROG0509.ASMPROG0510.ASMPROG0509.OBJPROG0509.OBJPROG0510x.ASM匯編鏈接ml/c/coffprog0509.asmml/c/coffprog0510.asmlinkprog0509.objprog0510.obj/out:prog0510x.exe/subsystem:consoleC語言模塊的反匯編C基本框架1: #include"stdio.h"2: intmain()3: {4: return0;5: }在C基本框架中,需要對部分寄存器初始化,并為局部變量在棧上開辟40h的空間,初始化為0CCh。反匯編碼-棧初始化過程00401020 55 push ebp00401021 8BEC mov ebp,esp00401023 83EC40 sub esp,40h00401026 53 push ebx00401027 56 push esi00401028 57 push edi00401029 8D7DC0 lea edi,[ebp-40h]0040102C B910000000 mov ecx,10h00401031 B8CCCCCCCC mov eax,0CCCCCCCCh00401036 F3AB repstos dwordptr[edi]00401038 33C0 xor eax,eax反匯編碼-棧初恢復(fù)過程0040103A 5F pop edi0040103B 5E pop esi0040103C 5B pop ebx0040103D 8BE5 mov esp,ebp0040103F 5D pop ebp00401040 C3 retC選擇結(jié)構(gòu)1: inti;2: if(i>=0)3: printf("iisnonnegative!");4: else5: printf("iisnegative!");00401049 837DFC00 cmp dwordptr[ebp-4],00040104D 7C0F jl main+3Eh(0040105e)0040104F 68840F4200 push offsetstring"iisnonnegative!"(00420f84)00401054 E887000000 call printf(004010e0)00401059 83C404 add esp,4;輸出printf("iisnonnegative!");0040105C EB0D jmp main+4Bh(0040106b)0040105E 68740F4200 push offsetstring"iisnegative!"(00420f74)00401063 E878000000 call printf(004010e0)00401068 83C404 add esp,4;輸出printf("iisnegative!");C循環(huán)結(jié)構(gòu)-for1: inti;2: for(i=1;i<=10;i++)3: ;00401038 C745FC01000000 mov dwordptr[ebp-4],1;局部變量i保存在棧中,通過[ebp-4]的方式訪問。0040103F EB09 jmp main+2Ah(0040104a)00401041 8B45FC mov eax,dwordptr[ebp-4]00401044 83C001 add eax,100401047 8945FC mov dwordptr[ebp-4],eax0040104A 837DFC0A cmp dwordptr[ebp-4],0Ah0040104E 7F02 jg main+32h(00401052)00401050 EBEF jmp main+21h(00401041)C-while循環(huán)00401038 C745FC01000000 mov dwordptr[ebp-4],1;局部變量i保存在棧中,通過[ebp-4]的方式訪問。0040103F 837DFC0A cmp dwordptr[ebp-4],0Ah;while(i<=10)00401043 7F0B jg main+30h(00401050)00401045 8B45FC mov eax,dwordptr[ebp-4]00401048 83C001 add eax,10040104B 8945FC mov dwordptr[ebp-4],eax0040104E EBEF jmp main+1Fh(0040103f)C變量定義局部變量保存在棧中,通過[ebp-n]的方式訪問。全局變量和靜態(tài)全局變量保存在內(nèi)存區(qū)域,通過邏輯地址訪問。1: #include"stdio.h"2: inti1; //全局變量3: staticinti2; //靜態(tài)全局變量4: intmain()5: {6: inti3; //局部變量7: i1=0;8: i2=0;9: i3=0;10: return1;11: }00401028 C705B827420000 mov dwordptr[_i1(004227b8)],0;全局變量i100401032 C705D825420000 mov dwordptr[i2(004225d8)],0;靜態(tài)變量i20040103C C745FC00000000 mov dwordptr[ebp-4],0;局部變量i300401043 B801000000 mov eax,1;返回值保存在eax0040104E C3 retC指針-內(nèi)存地址1: #include"stdio.h"2: intmain()3: {4: int*p,a;5: a=10;6: p=&a;7: }00401028 C745F80A000000 mov dwordptr[ebp-8],0Ah;a=10,a為局部變量,通過[ebp-n]的方式訪問。0040102F 8D45F8 lea eax,[ebp-8]00401032 8945FC mov dwordptr[ebp-4],eax;p=&a,p為局部變量,p中保存著a的地址。C函數(shù)1: #include"stdio.h"2: intsubproc(inta,intb)3: {4: returna*b;5: }6: intmain()7: {8: intr,s;9: r=subproc(10,8);10: s=subproc(r,-1);11: printf("r=%d,s=%d",r,s);12: }子程序subproc的反匯編碼-棧的初始化00401010 55 push ebp00401011 8BEC mov ebp,esp00401013 83EC40 sub esp,40h00401016 53 push ebx00401017 56 push esi00401018 57 push edi00401019 8D7DC0 lea edi,[ebp-40h]0040101C B910000000 mov ecx,10h00401021 B8CCCCCCCC mov eax,0CCCCCCCCh00401026 F3AB rep stos dwordptr[edi]返回值-保存在eax中00401028 8B4508 mov eax,dwordptr[ebp+8]0040102B 0FAF450C imul eax,dwordptr[ebp+0Ch];eax=a*b棧的恢復(fù)0040102F 5F pop edi00401030 5E pop esi00401031 5B pop ebx00401032 8BE5 mov
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(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ǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025版學(xué)校節(jié)日慶典活動(dòng)承包運(yùn)營合同3篇
- 2025年度個(gè)人商標(biāo)權(quán)抵押擔(dān)保許可協(xié)議書4篇
- 二零二五年度高速公路邊坡草皮修復(fù)合同模板3篇
- 網(wǎng)絡(luò)素養(yǎng)在學(xué)生職業(yè)發(fā)展中的重要性
- 二零二五年度車輛牌照租賃數(shù)據(jù)共享協(xié)議4篇
- 當(dāng)代企業(yè)網(wǎng)絡(luò)安全風(fēng)險(xiǎn)評估與防范措施匯報(bào)
- 教學(xué)資料數(shù)字化的應(yīng)用場景及案例分析
- 二零二五年度承臺基坑開挖施工勞務(wù)分包合同施工人員資質(zhì)要求4篇
- 數(shù)海導(dǎo)航小學(xué)數(shù)學(xué)知識框架構(gòu)建
- 安全知識教育在兒童成長中的角色
- T-GDASE 0042-2024 固定式液壓升降裝置安全技術(shù)規(guī)范
- 建筑工地春節(jié)留守人員安全技術(shù)交底
- 默納克-NICE1000技術(shù)交流-V1.0
- 蝴蝶蘭的簡介
- 老年人心理健康量表(含評分)
- 《小兒靜脈輸液速度》課件
- 營銷人員薪酬標(biāo)準(zhǔn)及績效考核辦法
- 醫(yī)院每日消防巡查記錄表
- 運(yùn)輸企業(yè)重大危險(xiǎn)源辨識及排查制度
- 運(yùn)動(dòng)技能學(xué)習(xí)與控制課件第五章運(yùn)動(dòng)中的中樞控制
- 中心血站改造項(xiàng)目謀劃建議書
評論
0/150
提交評論