[Opcode]JMP如何轉成機械碼的呢?

JMP一個指令,根據跳轉目的地遠近分成短跳轉(Short jump)、近跳轉(Near jump)、遠跳轉(Far jump)。


引用Intel指令手冊(Intel® 64 and IA-32 Architectures Software Developer’s Manual)裡面一些對於JMP的敘述:
  1. Short jump—A near jump where the jump range is limited to –128 to +127 from the current EIP value.
  2. Near jump—A jump to an instruction within the current code segment (the segment currently pointed to by the CS register), sometimes referred to as an intrasegment jump.
  3. Far jump—A jump to an instruction located in a different segment than the current code segment but at the same privilege level, sometimes referred to as an intersegment jump.
它們主要就是以所要跳的目的地位址與現在的IP(instruction pointer)位址差值來區分:
  1. 短跳轉:差值在 -128 ~ +127 (8-bit) 之內。
  2. 近跳轉:目的地在同一個區段內,且差值在 32-bit 可以表示的範圍內,又稱段內跳轉。
  3. 遠跳轉:目的地在別的區段,又稱段間跳轉。
雖然在組合語言都是以JMP來實現跳轉,但在組譯轉成機械碼(opcode)時翻譯出來的卻不一樣,短跳轉(EB)、近跳轉(E9)、遠跳轉(EA)。當然,機械碼不一樣就代表是不同的指令,其後的參數要怎麼給是該瞭解的事情。參考手冊說明摘要如下:
Opcode
Instruction
Short Jump
EB cbJMP rel8
Near Jump
E9 cw/cd JMP rel16/rel32
Far Jump
EA cd/cpJMP ptr16:16/ptr16:32
其中一些參數解釋:
  • rel8/rel16/rel32:偏移量(也就是上面說的差值)能用有號 8/16/32-bit 來表示的相對位址。
  • ptr16:16/ptr16:32:一個相對遠的指標(pointer),通常與IP不同區段,前面的16/16表示 16-bit 的區段暫存器,後面的16/32表示目的地在那個區段的偏移量。
  • cb, cw, cd, cp:用來描述代碼的偏移量和新的區段暫存器的值,分別為 1-byte、2-byte、4-byte、6-byte。
有概念之後,看程式來對上面敘述做驗證吧:
  1. 短跳轉:
  2. 位址Opcode
    Instruction
    003F1010 
    EB 06jmp  003F1018
    003F1012   
    EB 04jmp  003F1018
    003F1014
    EB 02jmp  003F1018
    因為指令位址距目的很近,所以為短跳轉(EB), EB 後的數字為目的地與 EIP 的偏移量,但可能有人會問,為什麼對不起來?像是第一個的
    偏移量 = 003F1018h - 003F1010h = 08h
    結果不是 EB 08,而是 EB 06 。這是因為 CPU 在運作時,看到 EB 06 知道要跳轉,也由於它已經讀了這一行指令, EIP 會再加 2 指向下一行,並執行 EB 06 這個指令。可以看得出關鍵嗎?在執行 EB 06 時 EIP 已經又加 2 了,實際上的算法應為
    偏移量 = 003F1018h - (003F1010h + opcode的長度) = 06h

  3. 近跳轉:
  4. 位址Opcode
    Instruction
    013D1035 
    E9 85 00 00 00
    jmp  013D10BF
    013D103A 
    E9 80 00 00 00jmp  013D10BF
    013D103F 
    EB 7E
    jmp  013D10BF
    偏移量的算法和短跳轉相同,不同在於近跳轉的 opcode 且 E9 與長度為 5-byte,在計算時要注意。在此特地用跳轉至同目的地但分別為近跳轉與短跳轉來說明,當從 1-byte 的 7E 要進位到 80 時,就會變成 4-byte 的 00 00 00 80h,因為其超出有號 8-bit 可表示範圍。
  5. 遠跳轉:
  6. 想到再說

留言

這個網誌中的熱門文章

[Hyper-V] 讓 Windows 可以吃到超過 16TB 的硬碟!