假設以下X86-32指令直接:有沒有辦法讓一個字大小在32位寄存器指令
add ebx,1
有(至少)兩個組裝操作碼的方式:
81 c3 01 00 00 00
或
83 c3 01
第一保持1作爲4字節DWORD 第二科eps 1作爲字節
是否有一條指令將1保留爲2個字節? 如果沒有,爲什麼?
假設以下X86-32指令直接:有沒有辦法讓一個字大小在32位寄存器指令
add ebx,1
有(至少)兩個組裝操作碼的方式:
81 c3 01 00 00 00
或
83 c3 01
第一保持1作爲4字節DWORD 第二科eps 1作爲字節
是否有一條指令將1保留爲2個字節? 如果沒有,爲什麼?
你已經偶然發現了x86指令集的怪癖。英特爾在第83
號詞彙下包含了一組指令,其第一個操作數的類型爲Ev
,其第二個操作數是一個直接字節,它被解釋爲與Ev
操作數的大小相同。因此,對於83 c3 01
,01
被解釋爲32位值;對於66 83 c3 01
,01被解釋爲16位值(並且目的地是16位ax
寄存器)。編碼爲6A
的push
助記符的行爲方式與單個操作數的大小相同。
您的問題的更廣泛的答案是否定的,沒有編碼的16位常量被解釋爲32位的編碼。我寫了一個反彙編程序。
您可能想解釋「Ev」的含義(如果OP不知道它是指通用寄存器或有效地址)。 –
謝謝,這爲我清除了一些東西。 – user1677989
66 81 C3 01 00(在32位模式下爲「add bx,01」)可能被認爲是一個例子。
有沒有這樣的例子,不需要覆蓋,因爲它不需要它。第一個示例需要四個字節的原因是它可以跨越整個4Gb範圍。第二個僅使用一個字節,因爲它限於+/- 128(總共256個值)。通過使用覆蓋,我們可以將第一個示例限制爲64kb,但實際上它不是兩個中的一個字節,它仍然是兩個字節。
'LEA EBX,[EBX + nn]'可以使用哪些編碼?這不會設置標誌,所以它不會被完全替代,但對於128到16777215之間的值,它可能比ADD更緊湊。 – supercat
@supercat可用值的集合是相同的 - 您可以將32位立即數用於4Gb值,或將單字節值用於符號擴展值。您也可以使用覆蓋67h將[EBX ...]更改爲[BX ...]以獲得64kb值。對於您的EBX示例,ADD和LEA的編碼大小是相同的。 –
我以爲表單有中等大小。可能不會。但我不認爲16位表格完全等同,因爲如果EBX是例如0x12345000,向BX添加0xBFFF會使EBX等於0x1234FFFF,但添加0xC000會使EBX等於0x12340000。 – supercat
在編程中使用小整數非常普遍 - 無論目標大小如何。好處是減少了指令編碼。許多指令支持:IMUL,ADD,ADC,SUB,SBB,AND,CMP等...此外,尋址模式支持字節大小的符號擴展偏移量以幫助減少代碼大小。
至於爲什麼不:我會收集增加的節省與字節編碼的節省相比是最小的。 ENTER指令確實使用16位立即數,但它是無符號的,並固定爲更新寄存器RSP/ESP/SP。
我最喜歡的是'inc ebx',或者將常量加載到另一個reg中,如果我打算使用它,然後'add ebx,reg'。 – 2013-06-29 14:38:56
爲什麼不呢?因爲它需要太多額外的操作碼或前綴。早在386年,英特爾意識到爲未來的擴展留下空間可能很重要,並沒有填補編碼空間。如果操作碼或前綴的長度比假設的'add r/m32,imm16'長1個字節,它只會保存一個字節而不是兩個字節。適合16位但不是8位的中立數是非常罕見的:大多數數字都是小的或指針,所以它不足以證明成本合理。 –