2010-03-31 118 views
49

在下面的彙編代碼我甩了使用objdump什麼是註冊%eiz?

lea 0x0(%esi,%eiz,1),%esi 

什麼是註冊%eiz?前面的代碼是什麼意思?

+1

您可能會發現http://sourceware.org/ml/binutils/2009-01/msg00081.html有趣。 – 2010-03-31 14:01:10

回答

51

Why Does GCC LEA EIZ?

顯然%eiz是(在MIPS像r0)一個僞寄存器,只是計算結果爲零時刻。

...

我最終發現的binutils大師伊恩·蘭斯·泰勒郵件列表後,揭示了答案。有時GCC會在代碼流中插入NOP指令,以確保正確對齊和類似的東西。 NOP指令需要一個字節,所以你會認爲你可以根據需要添加儘可能多的字節。但根據Ian Lance Taylor的說法,芯片執行一條長指令比多條短指令要快。因此,不是插入七條NOP指令,而是使用一個bizarro LEA,它使用了七個字節,並且在語義上等同於一個NOP。

+2

聰明的人:)謝謝你的答案! 因此上面的代碼只是nop的更長版本:P – Heartinpiece 2013-09-02 04:59:49

21

(遊戲很晚,但這似乎是一個有趣的補充):它根本不是一個寄存器,它是英特爾指令編碼的一個怪癖。當使用ModRM字節從存儲器加載時,有3個位用於寄存器字段來存儲8個可能的寄存器。但是ESP(堆棧指針)「將」所處的位置被處理器解釋爲「SIB字節遵循該指令」(即,它是擴展尋址模式,而不是ESP的引用)。由於作者只知道的原因,GNU彙編程序一直以「%eiz」寄存器的形式表示這個「零寄存器本來就是零」。英特爾語法只是放棄它。

+1

感謝分享:) – 2012-08-29 01:25:08

12

安迪羅斯提供了更多的底層推理,但不幸的是或者至少在技術細節上引起混淆。確實,只有(%esp)的有效地址不能用ModR/M字節進行編碼,而是被解碼爲(%esp),它用於表示還包含SIB字節。但是,%eiz僞寄存器並不總是與SIB字節一起使用來表示使用了SIB字節。 SIB字節(比例/索引/基數)有三個部分:索引(一個寄存器,例如%eax%ecx,該比例應用於),比例尺(2的冪從1到8)索引寄存器被乘以)和基址(被添加到縮放索引的另一個寄存器)。這是允許的指令,如add %al,(%ebx,%ecx,2)(機器碼:00 04 4b - 操作碼,modr/m,sib(注意即使使用SIB字節,也不注意%eiz寄存器))(或在Intel語法中,「add BYTE PTR [ecx * 2 + ebx],al「)。然而,%esp不能用作SIB字節中的索引寄存器。而不是允許這個選項,英特爾反而增加了一個選項來使用基址寄存器,因爲沒有縮放或索引。因此,爲了消除add %al,(%ecx)(機器碼:00 01 - opcode,modr/m)和add %al,(%ecx)(機器碼:00 04 21 - opcode,modr/m,sib)之間的歧義,替代語法add %al,(%ecx,%eiz,1)被改爲使用(或用於Intel語法:add BYTE PTR [ecx+eiz*1],al)。

並且如Sinan鏈接到的文章中所述,該特定指令(lea 0x0(%esi,%eiz,1),%esi)僅用作多字節nop(相當於esi = &*esi),因此只需執行一條nop指令而不是多條指令nop指令。