call和ret都是轉(zhuǎn)移指令。
它們修改IP或者同時修改CS和IP。
ret用棧中的數(shù)據(jù)修改IP實現(xiàn)近轉(zhuǎn)移。
retf用棧中的數(shù)據(jù)修改CS和IP的內(nèi)容實現(xiàn)遠(yuǎn)轉(zhuǎn)移。
ret實際執(zhí)行的步驟為:
(IP)=((SS)×16+(SP))
(SP)+=2
retf實際執(zhí)行的步驟為:
(IP)=((SS)×16+(SP))
(SP)+=2
(CS)=((SS)×16+(SP))
(SP)+=2
由于往高地處移動和出棧的操作方向相同,因為出棧也是站定指針向高地址處移動,并且它們用的都是SS和SP。
所以ret相當(dāng)于POP SP,retf相當(dāng)于POP IP,POP CS。
分兩步:
1、將當(dāng)前的IP或CS和IP壓入棧中。
2、轉(zhuǎn)移。
它不能實現(xiàn)短轉(zhuǎn)移。
10.3依據(jù)位移進(jìn)行轉(zhuǎn)移的call指令
call標(biāo)號
將當(dāng)前的IP壓棧后,再轉(zhuǎn)移到標(biāo)號處執(zhí)行指令。
具體步驟如下:
(SP)-=2
((SS)×16+(SP))=(IP)
(IP)+=(-215~215-1)
IP的位移實際為標(biāo)號處地址減去call指令后第一個字節(jié)的地址。
用匯編語言解釋如下:
PUSH IP
JMP NEAR PTR標(biāo)號
CALL FAR PTR標(biāo)號
它實現(xiàn)段間轉(zhuǎn)移,實際步驟如下:
1、(SP)-=2
((SS)16+(SP))=(CS)
(SP)-=2
((SS)16+(SP))=(IP)
2、(CS)表示標(biāo)號所在段的段地址,(IP)表示在段中的偏移地址。
用匯編語言解釋如下:
PUSH CS
PUSH IP
JMP FAR PTR標(biāo)號
用法:
call16位寄存器
作用為:
(SP)-=2
((SS)×16+(SP))=(IP)
IP是16位寄存器
匯編語言解釋如下:
PUSH IP
JMP16位寄存器
10.6轉(zhuǎn)移地址在內(nèi)存中的call指令
格式1:
call word ptr內(nèi)存單元地址
用匯編語言解釋如下:
PUSH IP
JMP WORD PTR內(nèi)存單元地址
格式2:
CALL DWORD PTR內(nèi)存單元地址
匯編語言解釋如下:
PUSH CS
PUSH IP
JMP DWORD PTR內(nèi)存單元地址
在這里可以總結(jié)一下call和ret。
call就是調(diào)用,它可以調(diào)用子程序。
ret就是return,即,返回,返回到調(diào)用處。
call是壓棧,ret是出棧。
call和ret搭配使用可以調(diào)用子程序,書寫的框架如下:
標(biāo)號:
指令
ret
P196~P197之間的程序段是個很好的例子。
P198給出了完整的程序調(diào)用架構(gòu),這就類似于函數(shù)調(diào)用。
mul:multiplication,乘法。
1、它要求乘數(shù)和被乘數(shù)位數(shù)相同,即,都是8位或者都是16位。
如果是8位,一個默認(rèn)放在AL中無需指定,另一個放在8位寄存器或者內(nèi)存字節(jié)單元中。
如果是16位,一個默認(rèn)放在AX中無需指定,另一個放在16位寄存器或者內(nèi)存字單元中。
2、結(jié)果。8位乘法結(jié)果放在AX中。16位乘法高位放在DX中,低位放在AX中。
格式如下:
mul寄存器/內(nèi)存單元
編寫子程序的標(biāo)準(zhǔn)框架:
子程序開始:子程序中使用的寄存器入棧
子程序內(nèi)容
子程序中使用的寄存器出棧
返回(ret,retf)
這一框架能夠解決程序中不同部分對寄存器使用沖突的問題。
div做除法運算是可能溢出的。
解決這一問題的辦法是使用公式,在P208有關(guān)于它的一個簡單說明。

它可以將一個可能產(chǎn)生溢出的除法運算變?yōu)槎鄠€不會產(chǎn)生溢出的除法運算。