2017-04-16 81 views
2

NASM返回如下錯誤:「在64位模式下不支持指令」,我無法弄清楚該怎麼做。主題指令是彈出和推送命令。我可以使用什麼來代替它們,或者有其他方法可以解決此問題嗎?64位模式不支持PUSH和POP指令

最好的問候......(我使用64位系統 - 英特爾酷睿i7處理器)

+0

顯示您的代碼,否則問題將無效。 「尋求調試幫助的問題(」爲什麼不是這個代碼工作?「)必須包含所需的行爲,特定的問題或錯誤以及在問題本身中重現問題所需的最短代碼。沒有明確問題陳述的問題對其他讀者無益' –

回答

8

總體思路是,你通常推而大如當前流行詞寄存器大小,所以你不能在64位模式下推送32位寄存器;相反,您可以推送並彈出整個64位寄存器,因此這是push rax而不是push eax。內存引用也是如此 - 您可以使用push qword ptr[rax],但不能使用push dword ptr[rax]

但是:即使在64位模式仍可以推:

  • 16位寄存器(push ax)和存儲器的引用(push word ptr[rax]);
  • 8位,16位和32位立即數;這通常由您的彙編程序自動處理爲優化(如果您使用push 1它將使用最緊湊的編碼進行編碼,該編碼將爲6A01,即imm8操作數)。
  • fsgs段寄存器但不csdsesss寄存器(其沒有真正在64位模式中使用)。

在所有這些情況下,小於64位的值(如push al)在符號堆棧上被符號擴展並推送爲64位值。這可以讓你做一個push -16AFF),匹配pop rax - 那就像你期望的那樣,它的工作原理與mov rax,-1完全一樣。

作爲一個例外,段寄存器或者是-擴展或推入堆棧並且進行16位移動(即堆棧上的另一個48位未被修改);這並不是什麼大問題,因爲pop fspop gs只是放棄這些額外的位。


最後,可以推16位或32個值(那些在上面的列表中指定)在64位模式而不它們延伸到64位 - 從而移動的只是2堆棧指針或4字節。這是用66hREX.W前綴編碼的,但是,如果您不小心,可能會使您產生未對齊的堆棧。

+0

除了可以推送r/m16和r/m64而不是r/m32的事實之外,事實上可以推送imm8,imm16和imm32而不是imm64是很奇怪的太。你不能推CS,DS,ES或SS,但你可以推FS和GS。相當不一致的IMO。 –

+0

@RudyVelthuis:它*很不一致,儘管在這個瘋狂中有一些方法。不能推送一個* imm64 *與其餘的指令集模糊不清 - 我知道接受* imm64 *的唯一指令是'mov r64,imm64'(實際上,它是* imm64的唯一匹配*在英特爾手冊中的整個指令集描述中)。除了* fs *和* gs *之外的段寄存器不再用於64位模式,所以它們不能被推送就不足爲奇了。 –

+0

我明白「瘋狂背後的方法」。但有時候它會讓人感到困惑。特別是你可以推/ 16位而不是32位的項目。 –