2013-06-29 38 views
4

假設以下X86-32指令直接:有沒有辦法讓一個字大小在32位寄存器指令

add ebx,1 

有(至少)兩個組裝操作碼的方式:

81 c3 01 00 00 00 

83 c3 01 

第一保持1作爲4字節DWORD 第二科eps 1作爲字節

是否有一條指令將1保留爲2個字節? 如果沒有,爲什麼?

+1

我最喜歡的是'inc ebx',或者將常量加載到另一個reg中,如果我打算使用它,然後'add ebx,reg'。 – 2013-06-29 14:38:56

+0

爲什麼不呢?因爲它需要太多額外的操作碼或前綴。早在386年,英特爾意識到爲未來的擴展留下空間可能很重要,並沒有填補編碼空間。如果操作碼或前綴的長度比假設的'add r/m32,imm16'長1個字節,它只會保存一個字節而不是兩個字節。適合16位但不是8位的中立數是非常罕見的:大多數數字都是小的或指針,所以它不足以證明成本合理。 –

回答

12

你已經偶然發現了x86指令集的怪癖。英特爾在第83號詞彙下包含了一組指令,其第一個操作數的類型爲Ev,其第二個操作數是一個直接字節,它被解釋爲與Ev操作數的大小相同。因此,對於83 c3 0101被解釋爲32位值;對於66 83 c3 01,01被解釋爲16位值(並且目的地是16位ax寄存器)。編碼爲6Apush助記符的行爲方式與單個操作數的大小相同。

您的問題的更廣泛的答案是否定的,沒有編碼的16位常量被解釋爲32位的編碼。我寫了一個反彙編程序。

+2

您可能想解釋「Ev」的含義(如果OP不知道它是指通用寄存器或有效地址)。 –

+0

謝謝,這爲我清除了一些東西。 – user1677989

0

66 81 C3 01 00(在32位模式下爲「add bx,01」)可能被認爲是一個例子。

有沒有這樣的例子,不需要覆蓋,因爲它不需要它。第一個示例需要四個字節的原因是它可以跨越整個4Gb範圍。第二個僅使用一個字節,因爲它限於+/- 128(總共256個值)。通過使用覆蓋,我們可以將第一個示例限制爲64kb,但實際上它不是兩個中的一個字節,它仍然是兩個字節。

+0

'LEA EBX,[EBX + nn]'可以使用哪些編碼?這不會設置標誌,所以它不會被完全替代,但對於128到16777215之間的值,它可能比ADD更緊湊。 – supercat

+0

@supercat可用值的集合是相同的 - 您可以將32位立即數用於4Gb值,或將單字節值用於符號擴展值。您也可以使用覆蓋67h將[EBX ...]更改爲[BX ...]以獲得64kb值。對於您的EBX示例,ADD和LEA的編碼大小是相同的。 –

+0

我以爲表單有中等大小。可能不會。但我不認爲16位表格完全等同,因爲如果EBX是例如0x12345000,向BX添加0xBFFF會使EBX等於0x1234FFFF,但添加0xC000會使EBX等於0x12340000。 – supercat

0

在編程中使用小整數非常普遍 - 無論目標大小如何。好處是減少了指令編碼。許多指令支持:IMUL,ADD,ADC,SUB,SBB,AND,CMP等...此外,尋址模式支持字節大小的符號擴展偏移量以幫助減少代碼大小。

至於爲什麼不:我會收集增加的節省與字節編碼的節省相比是最小的。 ENTER指令確實使用16位立即數,但它是無符號的,並固定爲更新寄存器RSP/ESP/SP。

相關問題