在別的語(yǔ)言中,程序進(jìn)行跳轉(zhuǎn)被看作是一種邏輯上的漏洞,想必學(xué)習(xí)過(guò)C語(yǔ)言的人都有這種認(rèn)識(shí),就是最好不要在程序中出現(xiàn)GOTO這個(gè)指令,不過(guò),跳轉(zhuǎn)在匯編語(yǔ)言中卻是一種很重要的語(yǔ)法,理解跳轉(zhuǎn)指令才能更好的駕馭匯編。
1.jmp指令
jmp指令是無(wú)條件的跳轉(zhuǎn)指令,jmp分為3種跳轉(zhuǎn)模式,一種是短轉(zhuǎn)移,一種是近轉(zhuǎn)移,最后是遠(yuǎn)轉(zhuǎn)移。首先介紹一下前兩種跳轉(zhuǎn):
jmp short 標(biāo)號(hào)?????????????? ;短轉(zhuǎn)移,程序跳轉(zhuǎn)到標(biāo)號(hào)標(biāo)注的地方,和C語(yǔ)言中的goto指令類似
jmp near prt 標(biāo)號(hào)?????????? ;近轉(zhuǎn)移,和短轉(zhuǎn)移類似
這兩種跳轉(zhuǎn)指令是不需要加上跳轉(zhuǎn)的地址的,他們屬于段內(nèi)跳轉(zhuǎn)指令,也就是說(shuō),他們只能改變IP的指向,而不改變CS的指向,他們跳轉(zhuǎn)依靠的是位移,這是編譯器在編譯的時(shí)候處理的事情,編譯器會(huì)將你的標(biāo)號(hào)地址減去jmp指令的地址,計(jì)算出之間位移,然后在翻譯成機(jī)器語(yǔ)言。位移為正就是向下跳轉(zhuǎn),位移為負(fù)就是向上跳轉(zhuǎn)。short和near prt之間的差別就是short跳轉(zhuǎn)的極限是2^7(8位位移),near的極限是2^15(16位位移)。
jmp far prt 標(biāo)號(hào)???????????? ;遠(yuǎn)轉(zhuǎn)移,和短轉(zhuǎn)移意思類似,只是細(xì)節(jié)不同
遠(yuǎn)轉(zhuǎn)移,又稱為段間轉(zhuǎn)移,它不僅僅會(huì)修改IP指向,還會(huì)修改CS的指向,這個(gè)跳轉(zhuǎn)的依據(jù)就是實(shí)實(shí)在在的地址。
那么,現(xiàn)在請(qǐng)思考為什么計(jì)算機(jī)會(huì)提供3種跳轉(zhuǎn)模式,或者說(shuō),為什么要出現(xiàn)依靠位移的跳轉(zhuǎn)指令,全部依靠絕對(duì)地址來(lái)跳轉(zhuǎn)難道不好嗎?
工程師絕對(duì)不會(huì)做出費(fèi)力不討好的事情,那么出現(xiàn)依靠位移的跳轉(zhuǎn)指令就一定有他的優(yōu)勢(shì)存在,思考以下情形,程序在內(nèi)存中運(yùn)行之時(shí)是需要被加載的,這個(gè)加載到的內(nèi)存地址是不確定的,也就是說(shuō)在這種情況之下,我們的遠(yuǎn)轉(zhuǎn)移指令很有可能找尋不到我們想要找尋的地址,那這時(shí),相等地址(位移)的優(yōu)勢(shì)就體現(xiàn)出來(lái)了,我們可以依靠位移來(lái)精確定位這個(gè)段中任意一個(gè)地址(在內(nèi)存中的浮動(dòng)裝配),而不需要具體的地址,但是這也引發(fā)了一個(gè)很奇怪的程序,我們最后再來(lái)介紹。
2.loop,jcxz指令
loop指令,顧名思義,就是循環(huán)指令,語(yǔ)法和jmp指令類似:
loop 標(biāo)號(hào)???????????????????????? ;跳轉(zhuǎn)到標(biāo)號(hào)處
還記得前面介紹的CX寄存器嗎,這里就是輪到他大顯生手的地方了,loop指令是依靠CX的值來(lái)判斷循環(huán)次數(shù)的,只要CX不為0,那么loop就執(zhí)行跳轉(zhuǎn),那么loop指令用偽代碼來(lái)描述就是:
if(CX != 0)? dec CX? jmp 標(biāo)號(hào)??????? ;dec是自減的意思
那么有了CX不為0,則跳轉(zhuǎn)的指令,有沒(méi)有另一個(gè)當(dāng)CX等于0時(shí),跳轉(zhuǎn)的指令?當(dāng)然,jcxz指令就是這種功能,看字面意思就是jmp (cx = zore),jcxz指令用法和jmp完全一致,只是jcxz執(zhí)行之時(shí)首先會(huì)去檢查CX寄存器的值。
3.一段奇怪的程序
好的,現(xiàn)在是不是很好奇之前所提到過(guò)的那個(gè)很奇怪的程序,那么我們現(xiàn)在開(kāi)始介紹,想必在理解過(guò)這段奇怪的程序之后,你會(huì)對(duì)jmp這個(gè)指令有著更加深入的理解。
這是這本書(shū)的作者,王爽老師提供的程序,下面上圖:

現(xiàn)在思考,這個(gè)程序運(yùn)行是怎么樣運(yùn)行?他能正常退出嗎,也就是執(zhí)行到程序退出的出口。
如果你認(rèn)為它可以正常的退出,那么恭喜你,你已經(jīng)理解jmp指令了,如果你認(rèn)為它是在標(biāo)號(hào)S1,S2處不斷的循環(huán),那么請(qǐng)仔細(xì)回顧一下一開(kāi)始所說(shuō)的短轉(zhuǎn)移指令。
是的,這里的短轉(zhuǎn)移指令最后翻譯出來(lái)的意思是向上移動(dòng)S2-S1(地址)個(gè)字節(jié),于是程序最后就在標(biāo)號(hào)S處向上跳轉(zhuǎn)到了這個(gè)段的最開(kāi)頭,也就是程序的出口,成功退出。