轉移指令的原理

TFOREVERY發表於2023-04-15

轉移指令有如下:

1.無條件轉移指令(如:jmp)

2.條件轉移指令

3.迴圈指令(如:loop)

4.過程

5.中斷

運算子offset(取得標號的偏移地址)

jmp指令 --> 可以只修改IP ,也可以同時修改 CS 和 IP(實際是根據位移來轉移的指令)

怎麼計算位移

位移:該 jmp 要跳轉到的標號內的第一個指令的偏移地址 減去(-)jmp 指令下一指令的偏移地址

機器碼的位元組數一般為 2 ~ 3 個位元組 --> 機器本身的位元組(1個位元組) + 值的位元組(暫存器的位元組為2,al,ah等的位元組為1)(值分為1位元組值,如:21h --> (轉化成彙編裡的值)21 等,2位元組值,如:2000h --> (轉化成彙編裡的值)0020),用來計算當前指令下一指令的偏移地址

jmp後的偏移地址為(即IP的值): jmp 下一條指令的偏移地址 + 位移(可能為正也可能為負)

https://fishc.com.cn/thread-27458-1-1.html
(借鑑的網站)

這裡注意,此位移的計算只能適用於原有的語句,經過複製後得到的語句位移不變,即複製過後的語句的執行後的 ip == 該語句之下的一條語句 + 原有語句計算出來的位移

如:

首先我們能計算出 jmp short s 的 位移量 為 0008-0018 = -10(注意這裡是十六進位制的-10 --> (二進位制)-16)
則執行 jmp short s 後ip 應該 == 0018 + (-10) == 0008 --> 恰好對應 s 的偏移地址
其次我們也能計算處 jmp short s1 的 位移量 為 0018-0022 = -10(注意這裡是十六進位制的-10 --> (二進位制)-16)
由於 s 中的 jmp short s1 是複製過去的所以位移量不變 == 0018-0022 = -10 所以當執行 s 中的 jmp short s1 時
ip == 000A + (-10) = 0
可能的問題:
(1)s 中不是有兩個 nop(nop指,這是一條空語句) 嗎?為什麼複製過後一個都沒了呢? --> 這個跟機器碼所佔的位元組有關,nop 所佔的位元組為 1,兩個恰好是2位元組,而jmp short s1 這條指令所佔的位元組為2位元組,剛好覆蓋了兩個nop
(2)為什麼使用000A來計算而不是0009來計算呢?--> 與問題1有關,複製後的程式碼應該如圖:

可以清楚的看到0008和0009這兩偏移地址被用來存放jmp short s1 這一語句了

需要:

轉移的目的地址

轉移的距離(段間轉移,段內短轉移,段內近轉移)

jmp short 標號(轉到標號處執行指令)

此種格式的jmp指令實現的是段內短轉移
對IP的修改範圍為 -128 ~ 127
即向前轉移最多可以越過128個位元組
向後轉移最多可以越過127個位元組

jmp near ptr 標號

該實現的是段內近轉移
對IP的修改範圍為 -32769 ~ 32767
即向前轉移最多可以越過32769個位元組
向後轉移最多可以越過32767個位元組

以上兩種轉移都是基於當前的IP的轉移

jmp far ptr 標號

實現的是段間轉移 --> 遠轉移

far ptr 指明瞭指令用標號的段地址和偏移地址,修改CS和IP

jmp 16為暫存器

功能:IP = (16位暫存器所存的值)
(1)jmp word ptr 記憶體單元地址(段內轉移)
該記憶體單元地址處開始存放著一個字(資料),該字(資料)就是轉移的目的偏移地址
(2)jmp dword ptr 記憶體單元地址(段間轉移)
該記憶體單元地址處開始存放著一個兩個字(資料),高地址處的字(資料)是轉移的目的的段地址,低地址處的字(資料)是轉移的目的的偏移地址(第一個字(資料)為低地址,第二個字(資料)為高地址)

所有的有條件轉移指令都是段轉移,對IP的修改範圍都為 -128 ~ 127

jcxz指令(有條件轉移指令)

格式:jcxz 標號

如果 cx = 0 那麼轉移到標號處執行
反之,則執行該語句的下一條指令,即跳過jcxz指令

loop指令(有條件轉移指令)

格式 loop 標號

如果 cx != 0 那麼轉移到標號處執行
反之,則執行該語句的下一條指令,即跳過jcxz指令

值得注意的是,loop的指令執行時,首先dec cx,後才判斷cx是否為0 --> 是否繼續迴圈 (可以利用這個判斷機制完成9.3的檢測(不需要jcxz指令))

相關文章