2016-10-29 323 views
6

我是一個新手,剛開始學習彙編語言。所以請糾正我,如果我錯了,或者如果這篇文章沒有任何意義,我會刪除。x86-64中movq和movabsq的區別

我說的是在X86-64英特爾架構的數據移動指令。我已經知道常規的movq指令只能有立即源操作數,可以用32位二進制補碼錶示,而movabsq指令可以有一個任意的64位立即數作爲其源操作數,並且只能有一個寄存器作爲目的地。

請您詳細說明一下嗎?這是否意味着我只能使用movabsq指令移動64位立即數?只有從立即價值到註冊?我看不出我能如何將64位立即數值移到內存中。或者我在這裏弄錯了一些重要的東西。

+2

你必須將它移動到一個寄存器然後移動到內存。這裏的所有都是它的。 –

回答

11

在NASM/Intel語法中,mov r64, 0x...根據常量選擇a MOV encoding。有四種可選擇的立即操作數:

  • 5字節mov r32, imm32。 (zero-extended to fill the 64-bit register like always)。 AT & T:mov/movl
  • 6字節mov r/m32, imm32。僅對內存目標有用。 AT & T: mov/movl
  • 7字節mov r/m64, sign-extended-imm32可以將8個字節存儲到內存,或將64位寄存器設置爲負值。 AT & T:mov/movq
  • 10字節mov r64, imm64。 (這是REX.W = 1版本相同的操作碼作爲mov r32, imm32的)AT & T:movabs

(字節計數僅用於寄存器的目的地,或尋址不需要一個SIB字節或DISP8模式/ disp32對比:只是操作碼+ MODR/M + IMM32)


在氣體與AT & T語法

movabsq意味着機器代碼編碼將包含一個64位值:或者是一個立即數,或者是一個絕對內存地址。沒有movabsq,它不能。

使用AT & T語法在此what's new in x86-64 guide中提到了其中的一些。除非你想要一個更長的指令用於對齊的目的(而不是稍後用NOP填充),否則不要使用mov $1, %rax。使用mov $1, %eax獲取5字節的格式。

有趣的實驗:movq $0xFFFFFFFF, %rax可能不是encodeable,因爲它不是一個符號擴展 32位立即所能表述的,並且需要無論是imm64編碼或%eax目的地編碼。

movabs與直接來源永遠是imm64形式。 (movabs也可以是以64位絕對地址和RAX作爲源或目標的MOV編碼:如REX.W + A3MOV moffs64, RAX)。


一些Intel的語法彙編器(但不是GAS)將優化的32位常數到5字節mov r32, imm32(NASM做到這一點),而其他(如YASM)將使用7字節mov r/m64, sign-extended-imm32。他們都選擇imm64編碼只用於大常量,而不必使用特殊的助記符。


我不知道怎樣才能在64位立即值轉移到內存中。

這是一個單獨的問題,答案是:你不能。 insn ref manual entry for MOV說明了這一點:具有imm64立即數操作數的唯一形式只有一個寄存器目的地,而不是r/m64。

如果您的值適合符號擴展的32位立即數,則movq $0x123456, 32(%rdi)將執行一個8字節的存儲至存儲器。限制是它只是一個imm32。

+0

[從64位地址加載到rax以外的其他寄存器](http://stackoverflow.com/q/19415184/995714) –

+0

爲什麼'movq $ 0xFFFFFFFF,%rax'不可編​​碼?爲什麼5字節版本不工作? –

+0

@LưuVĩnhPhúc:因爲您使用了'movq'。爲了讓gas使用5字節的無REX前綴編碼,你必須自己進行優化並寫入'movl $ 0xFFFFFFFF,%eax'。所以它就像YASM一樣,不會爲你優化它。 –