2017-05-24 164 views
0

我用下面的代碼創建了一個簡單的C++源文件。彙編語言機器代碼

int main() { 
int a = 1; 
int b = 2; 
if(a < b) { 
    return 1; 
} 
else if(a > b) { 
    return 2; 
} 
else { 
    return 3; 
} 

}

我用objdump的命令來獲取上述源代碼的彙編代碼。 併線

INT B = 2;轉換爲mov DWORD PTR [rbp-0x4],0x2

而其相應的機器碼(十六進制格式)是c7 45 fc 02 00 00 00

我想知道如何將彙編代碼轉換爲二進制代碼。我查閱了x86-64的英特爾參考手冊,但由於我是低級編程的新手,所以我無法理解。

+1

「轉換」是什麼意思?使用程序?手動做? – Shiro

+0

手動轉換它。 –

+0

'int b = 2;'不是彙編語言。不同之處在於,C是編譯語言,所以'int b = 2;'這行可以用許多不同的方式實現(甚至可以被優化器徹底刪除),這取決於編譯器將決定什麼,如何生成機器碼結果由C語言標準定義。彙編語言的方式不同,彙編程序不是這種類型的編譯器,當你在Assembly'add rax,rbx'中編寫時,它將被編譯爲這樣,不會改變指令,或者被某種優化器刪除,所以這更像是「1:1變革」。 – Ped7g

回答

4

你應該閱讀英特爾手冊,它解釋瞭如何做到這一點。爲更簡單的參考,read this。 x86指令的編碼方式非常簡單,但可能性有點過大。

簡而言之,x86指令包括以下部分,其中除了所述操作碼每一個部分可能丟失:

prefix opcode operands immediate 

prefix字段可以修改指令的行爲,這並不適用於你的用例。您可以在參考文獻(我喜歡this one)中查找opcode,例如,mov r/m32, imm32C7 /0,這意味着:操作碼是C7,兩個操作數中的一個是零作爲擴展操作數。該指令需要一個32位的立即的,所以指令的形式

C7 operand/0 imm32 

操作數/擴展操作碼被編碼爲具有可選的SIB(標度指數基)字節用於一些尋址模式和一個MODR /米字節可選的8位或32位移位。你可以看看你需要什麼值in the reference。因此,在你的情況下,你想編碼一個存儲器操作數[rbp]與一個字節的位移和寄存器操作數爲0,導致modr/m字節45。所以編碼是:

C7 45 disp8 imm32 

現在我們編碼二進制補碼中的8位移位。 -4對應FC,所以這是

C7 45 FC imm32 

最後,我們編碼32位立即,你想成爲2。請注意,它是在小端:

C7 45 FC 02 00 00 00 

這就是如何指令編碼。

+0

因此,在你提供的[鏈接](http://ref.x86asm.net/geek64.html)中,我去了C7 1字節操作碼,它用於** MOV **指令。但是兩個操作數Evqp \t和Ivds \t的含義是什麼,它們是否對應於rm32尋址和直接?感謝您的幫助 –

+0

請參閱[本頁](http://ref.x86asm.net/#column_op)瞭解這些字段的含義。我鏈接的參考文獻是高度濃縮的,但更難以閱讀。 – fuz

+0

好,太好了。另一個問題是,你說「我想用1字節的位移(8位)[** DWORD PTR [rbp-0x4] **]對rbp寄存器進行編碼」,當我看到MOD [r/m]鏈接](http://ref.x86asm.net/geek64.html#modrm_byte_32_64)我也看到一個32位位移的版本,你能給我一個例子嗎? –