2017-10-15 4180 views
6

我有一個工具生成的x86_64體系一些GNU彙編代碼,並有以下說明:什麼是callq指令?

movq %rsp, %rbp 
leaq str(%rip), %rdi 
callq puts 
movl $0, %eax 

我無法找到關於「callq」指令實際的文件。

我看過http://support.amd.com/TechDocs/24594.pdf這是「AMD64體系結構程序員手冊第3卷:通用和系統指令」,但它們只描述CALL近和遠指令。

我已經看過gnu assembler https://sourceware.org/binutils/docs/as/index.html的文檔,但找不到詳細說明它支持的說明。

我明白,它是一個函數的調用,但我想知道細節。我可以在哪裏找到它們?

+0

我很好奇,@彼得,爲什麼你經常發表你的答案作爲評論而不是答案。 – prl

+1

@prl:我這樣做的時候,我認爲他們可能是重複的,但我沒有花時間去尋找重複目標。我會看看這個;如果它不是重複的,那麼值得寫出真實的答案。你說得對,我可以把它作爲答案。 –

+2

@prl:我沒有發現任何關於'callq'的具體問題。實際上有些非明顯的東西可以說明分支和其他堆棧指令的默認操作數大小。這是一個新手問題,但實際上值得迴應改變的是,如果我停止對所有不良行爲表現出脾氣暴躁的「我的代碼不起作用,我什麼都不知道」的問題。 –

回答

7

這只是call。如果您想查看英特爾/ AMD手冊中的說明,請使用英特爾語法反彙編。

q操作數大小後綴在技術上適用(它推送64位返回地址並將RIP視爲64位寄存器),但無法用指令前綴覆蓋它。即calllcallw不能在64位模式下編碼,所以它只是令人討厭的是一些AT語法工具將其顯示爲callq而不是call。這當然也適用於retq

不同的工具在32位和64位模式下有所不同。 (Godbolt

  • GCC -S:總是call/ret。尼斯。
  • 鏗-S:callq/retqcalll/retl。至少它一直很煩人。
  • objdump -d:callq/retq(顯式64位)和call/ret(隱含於32位)。不一致和有點愚蠢,因爲64位沒有操作數大小的選擇,但是32位。 (不是有用選擇,雖然:callw截斷EIP到16位)

    儘管在另一方面,默認的操作數大小(沒有REX.W前綴)在64位模式指令仍然是32.但是add $1, (%rdi)需要操作數大小的後綴;如果沒有任何暗示,彙編器將不會爲你選擇32位。 OTOH,push暗含爲pushq,即使pushw $1pushq $1都是可編碼的(and usable in practice)在64位模式下。


從Intel的指令集REF手冊(上面鏈接):

對於近呼叫絕對的,絕對是在通用寄存器或內存位置間接地指定的偏移量(r/m16,r/m32或r/m64)。 操作數大小屬性決定了目標操作數的大小(16,32或64位)。在64位模式下,近端調用(和所有近端分支)的操作數大小被強制爲64位

for rel32 ...與絕對偏移量一樣,操作數大小屬性決定了目標操作數(16,32或64位)的大小。 在64位模式下,目標操作數將始終爲64位,因爲操作數大小在接近分支時被強制爲64位。

在32位模式中,可以編碼一個16位call rel16該截斷EIP到16位,或使用一個絕對的16位地址的call r/m16。但是如手冊所述,操作數大小在64位模式下是固定的。

+1

我喜歡這種形式「持續煩人」。