2010-03-30 49 views
7
0x004012d0 <main+0>: push %ebp 
0x004012d1 <main+1>: mov %esp,%ebp 
0x004012d3 <main+3>: sub $0x28,%esp 

如果地址不可用,我們可以自己計算嗎?每個指令在x86程序中編譯多少個byes?

我的意思是,我們只有這一點:

push %ebp 
mov %esp,%ebp 
sub $0x28,%esp 
+0

你想在運行時?即'asm_size(「mov esp,ebp」)'? – 2010-03-30 16:15:00

+3

這種東西是依賴於硬件架構的。這不是一個「分析」問題,而是一個「查找合適的詞典」問題。 – billyswong 2010-03-30 16:28:49

+0

在Linux中,您可以使用'objdump -d executable-file'來查看操作碼,然後您會看到每條指令的大小 – jyz 2010-10-10 00:06:35

回答

0

如果您有文字的彙編代碼,你將不得不使用一個assemb LER例程獲得
二進制表示,並且因此指令(S)的大小。當然,這是硬件依賴。

例如,這裏是一個80x86 32-bit Assembler打開source codeOllyDbg v1.10)。

1

第一指令是在[主+ 0],第二個是在[主+ 1],從而所述第一指令是1個字節。第三條指令在[main + 3]處,所以第二條指令是兩個字節。你不能從列表中知道第三條指令是多久,因爲它沒有顯示4.指令的地址。

3

您無法從助記符中確定指令大小。這裏有一些特殊情況:

  • 如果你在一個16位段的時候,mov eax, 0需要0x66前綴,而在32位段沒有。你需要知道細分市場的規模。

  • 在32位或16位模式

    你可以編碼add eax, 1如任一0x40inc eax)或0x83 0xc0 0x01add eax, 1)。也就是說,有一些助記符可以用多種方式編碼。

  • 存儲器操作數[eax]可以將eax編碼爲基數或索引。如果它是索引,則在MOD/RM之後會有一個額外的SIB字節。

  • 在64位模式下,您可以使用REX前綴0x4x對寄存器r8 - r15進行編碼。但是,您可以使用0x40作爲某種空REX字節,這會將另一個字節添加到您的指令中。

  • 段覆蓋可以使用,即使明確的段是相同的隱式之一。

還有很多其他的方式來使用更多或更少的字節對指令進行編碼。一個好的彙編程序應該總是使用最短的彙編程序,但是架構當然不需要它。好處是,如果您學習英特爾IA-32軟件開發人員手冊的第2卷,您應該可以自己解決這個問題。

+0

的確,指令編碼,特別是x86/x64上的指令編碼是不明確的,兩個彙編助記符都可以描述相同的指令('xchg ax,ax'和'nop'),並且可能存在可以是組合助記符的兩個二進制操作碼(32位中的「inc eax」 - 「0x40」和「0xff 0xc0」)。他們甚至有時故意含糊不清的原因,如'NOP'指令,請參閱http://stackoverflow.com/questions/2123000/dummy-operations-handling-of-intel-processor/2124407#2124407 – 2011-03-22 11:08:48

+0

許多舊的指令可以也可以用VEX或EVEX前綴重新編碼,因此它們將具有不同長度的多個表示 – 2018-02-24 08:39:56

+0

@LưuVĩnhPhúc:這不太準確。使用VEX或EVEX編碼爲AVX的SSE指令具有稍微不同的行爲: *它們具有不同的啓用要求。例如,VEX需要CR4.OSXSAVE和XCR0中的各個位。 * 128位AVX指令清除YMM或ZMM的高位,而相應的SSE指令則保留高位不變 – 2018-02-24 18:53:39

0

如果可能的話,彙編程序會生成一個列表。這將顯示你的源代碼,接下來將是指令的二進制表示,你需要做的是統計有多少字節,然後你得到的大小。