x86結構機器碼識別及其反彙編

 Intel的IA32-x86體系結構CPU的每條指令都可能由以下六個域組成,並且它們在指令中的排列順序是不能改變的。

  這六個域分別是:
            prefixes (1 Byte)
            code (1/2/3 Bytes;2字節指令是第一個指令碼爲0x0f,而一般3字節指令的第3字節是ModR/M的一部分)
            ModR/M (1 Byte)
            SIB (1 Byte)
            displacement (1/2/4 Bytes)偏移量
            immediate (1/2/4 Bytes)立即數
  在任何一條指令中code域必須出現,其他的域都是可選的。
  由於這六個域在指令中的排列順序是固定的,所以反彙編機器碼,就是一個對它們的依次識別過程。
  1、對prefixes的識別  
  x86體系結構CPU的4類prefixes,它們分別爲:
            lock/repeat prefix      :F0/F2,F3 (LOCK和REP)
            segment override prefixes      :2E,36,3E,26,64,65 (忽略段的前綴)
            operand-size override prefix        :66 (忽略操作數大小的前綴)
            address-size override prefix        :67 (忽略地址大小的前綴)  
  指令的prefixes可以由這幾類prefixes組成,但是每類prefixes只能在指令中出現一次,至於每類prefixes在指令的出項順序是沒有要求的,這點和指令的六個域是不同的。當某類prefixes在同一指令中出現多次的時候,CPU在執行過程中,可能會出現不可預料的結果,至於會不會出現異常,Intel的官方手冊中只用了這句話來說明:such use may cause unpredictable behavior.鬼知道會出項什麼情況,因此算法必須對這類機器碼具有識別能力。但是也可能異常情況不會發生,在反彙編過程,遇到同一類prefixes出現多次的情況,以最後出現的prefix爲準,進行機器碼識別。
  總結:
    (1)Prefixes是唯一的一個可能出現在code之前的域。
    (2)所有的Prefixes都只有1個字節。 
    (3)在一個OpCode中可能會有多個Prefixes
    (4)如果有多個Prefixes,那麼它們的順序可以打亂,不會有任何問題。
    (5)如果Prefixes不能對隨它之後的OpCode起作用,那麼它就會被忽略。
    2、對code和operand的識別 
    CPU在設計時,爲了提高比特位的利用率,也爲了保證一個code不是另一個code的前綴(否則CPU也無法譯碼),code的編碼採用的是哈夫曼算法。code的最大長度是3個字節,當然可以是1個字節,也可以是2個字節,另外,對於某些特定的code,還有3個比特的信息也會用來表示code.這3比特在ModR/M的3、4和5位。當然每個code也最多只能有三個operand。
    對code的識別一般都是採用二維表格來驅動的。二維表格中記錄了給各code的詳細信息。
    ModR/M字節:這個字節指示了後面跟隨的操作數的形式,它分成3個部分:第7-6位是Mod部分,第5-3位是Reg部分,第2-0位是R/M部分,其中Mod和R/M部分結合指示了指令操作數的尋址方式,而Reg部分主要是指示用到的寄存器,這個字節的解釋要和主操作碼結合起來。
    SIB字節:除了上面這個ModR/M字節外,有時候指令還需要一個字節來補充指操作數的尋址方式,這個字節也分成3個部分:第7-6位是scale部分,第5-3位是index部分,第2-0位是base部分;
    在翻譯過程中,以指令的操作碼爲索引從相應的數組來輸出對應的指令字符串,而接下來最主要的就是對操作數的翻譯,所有的操作數都可以用:【尋址方式 + 操作數類型】來表示,尋址方式有A(直接地址),C(ModR/M字節的REG部分指示一個控制寄存器),D( ModR/M字節的REG部分指示一個調試寄存器),E(ModR/M字節指示的操作數是一個通用寄存器或一個內存地址),F(EFLAGS寄存器),G(ModR/M字節的REG部分指示一個通用寄存器),I(立即數),J(指令包含一個相對地址),M(ModR/M字節指示一個內存地址),O(沒有ModR/M字節,後面的字或雙字爲偏移地址),P(ModR/M字節的REG部分指示一個4字節MMX寄存器),Q(ModR/M字節指示的操作數是一個MMX寄存器或一個內存地址),R(ModR/M字節的Mod部分指示一個通用寄存器),S(ModR/M字節的REG部分指示一個段寄存器),T(ModR/M字節的REG部分指示一個測試寄存器),V(ModR/M字節的REG部分指示一個128位XMM寄存器),W(ModR/M字節指示的操作數是一個128位XMM寄存器或一個內存地址),X(內存地址由DS:SI寄存器對錶示),Y(內存地址由ES:DI寄存器對錶示);操作數類型主要有b(字節),d(雙字節),w(字),v(字或雙字,根據操作數大小定)。 
    3、現在就可以根據下面的兩個表來進行機器碼識別了。例如,如果二進制序列是0x03,0x70,0xe8,則操作碼是0x03,查指令表Table A-2是"add Gv,Ev",第2個字節0x70是ModR/M字節,二進制是01110000,則Mod部分是1,REG部分是6,R/M部分是0,查ModR/M字節表Table 2-2得到Gv操作數是esi,Ev操作數是[eax+disp8],disp8是8位的偏移量,則讀下一個字節0xe8,由於這個字節是負數,取相反值是0x18,則Ev操作數是[eax-0x18],所以輸出的最終指令是"add esi,[eax-0x18]"。
                      image
                      image
    4、擴展指令
    除了單字節指令和二字節指令外還有一部分指令是三字節的,這些指令稱作擴展指令,擴展指令是把ModR/M字節當作操作碼的一部分,根據指令屬於的不同group和REG部分的值來查Intel Manual中表Table A-4翻譯指令的,如操作碼爲0x80-0x83的指令就是屬於group 1,然後根據REG的值來確定操作碼的字符串,如REG爲5則是"sub"指令。
    5、浮點數指令
    浮點數指令又叫逃逸碼指令(escape opcode instructions。它是主操作碼爲0xd8-0xdf的指令,並且用這個主操作碼分成幾組,每組指令中又根據ModR/M字節的值分成值在0x00-0xbf範圍中和不在這個範圍中兩部分,在這個範圍中的指令根據ModR/M字節字節中的REG部分進行索引,得到相應的指令;不在這個範圍中的指令則按照ModR/M字節的值查找相應的表得到指令,ModR/M字節中的高4位是行號,低4位是列號。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章