一文詳解匯編語言call和ret指令
什么是call?
在我們平時編程過程中,都會用到函數(shù)或子程序,反匯編就是call指令。可以使程序跳轉(zhuǎn)到指定代碼段,執(zhí)行結(jié)束后,返回主程序繼續(xù)向下執(zhí)行。
分析如下代碼段,程序執(zhí)行后,ax寄存器中的數(shù)值為多少?
首先,mov ax,0執(zhí)行結(jié)束后,ax寄存器中的值為0,該指令機器碼長度為3字節(jié),因此,ip=3。
call far ptr s執(zhí)行后,程序會跳轉(zhuǎn)到標(biāo)號s處,但是需要將該指令的下一條指令地址保存起來,s段執(zhí)行后要返回。因此push cs=1000,push ip=8。再跳轉(zhuǎn)cs=1000,ip=9。
pop ax執(zhí)行后,ax=8h;
add ax,ax執(zhí)行后,ax=10h;
pop bx執(zhí)行后,bx=1000h;
add ax,bx執(zhí)行后,ax=1010h;
由于s沒有返回,最終ax寄存器中的值為1010h。
call 寄存器
call后面不僅可以加標(biāo)號,也可以直接加寄存器。
call ax執(zhí)行后,將下一條指令inc ax的偏移地址ip入棧,因此sp指向的內(nèi)存中數(shù)據(jù)為5。然后ip=6;
mov bp,sp執(zhí)行后,bp指向的內(nèi)存空間數(shù)據(jù)也為5;
add ax,[bp]執(zhí)行后,相當(dāng)于ax=ax+5=11,即0bh。
轉(zhuǎn)移地址在內(nèi)存中的call指令
語法:call word ptr 內(nèi)存單元地址
相當(dāng)于:
push IP
jmp word ptr 內(nèi)存單元地址
執(zhí)行如下指令:
mov sp,10h
mov ax,0123h
mov ds:[0],ax
call word ptr ds:[0]
最終跳轉(zhuǎn)到ds:[0]=0123h,(IP)=0123H,SP=0EH(10H-2H=0EH)。
語法:call dword ptr 內(nèi)存單元地址
相當(dāng)于:
push CS
push IP
jmp dword ptr 內(nèi)存單元地址
執(zhí)行如下指令:
mov sp,10h
mov ax,0123h
mov ds:[0],ax
mov word ptr ds:[2],0
call dword ptr ds:[0]
執(zhí)行后,ds中數(shù)據(jù)類型為dword,0-1的word類型數(shù)據(jù)為0123h,因此(IP)=0123h;2-3的word類型數(shù)據(jù)為0,因此(CS)=0,入棧dword類型是4個字節(jié)數(shù)據(jù),(SP)=10h-4h=0ch。
閱讀程序
分析如下程序,最終ax寄存器中的值為多少?(debug調(diào)試會因為中斷問題造成和理論分析不一致)
首先,??臻g16個字節(jié)0,ss棧段為ax,ds數(shù)據(jù)段也是ax;
ax初始值為0;
當(dāng)執(zhí)行call時,首先將call下方第一個inc ax的IP入棧,(SP)=0EH,并跳轉(zhuǎn)至ds:[0EH],這個值就是SP指向空間保存的IP,程序正常向下運行,inc ax執(zhí)行三次,最終(ax)=03H。
ret指令
call指令執(zhí)行時,將當(dāng)前指令的下一條指令偏移IP保存入棧,然后跳轉(zhuǎn)至標(biāo)號處,也就是我們說的函數(shù),函數(shù)執(zhí)行完畢,ret指令會將IP彈出。
上述程序,call s執(zhí)行三次add ax,ax,最終(ax)=8,然后返回至mov bx,ax,(bx)=08h。