https://stackoverflow.com/questions/56122039/what-are-the-meanings-of-callq-command-parameters
It's just call
. Use Intel-syntax disassembly if you want to be able to look up instructions in the Intel/AMD manuals.
The q
operand-size suffix does technically apply (it pushes a 64-bit return address and treats RIP as a 64-bit register), but there's no way to override it with instruction prefixes. i.e. calll
and callw
aren't encodeable in 64-bit mode, so it's just annoying that some AT&T syntax tools show it as callq
instead of call
. This of course applies to retq
as well.
Different tools are different in 32 vs. 64-bit mode. (Godbolt)
- gcc -S: always
call
/ret
. Nice. - clang -S:
callq
/retq
andcalll
/retl
. At least it's consistently annoying. -
objdump -d:
callq
/retq
(explicit 64-bit) andcall
/ret
(implicit for 32-bit). Inconsistent and kinda dumb because 64-bit has no choice of operand-size, but 32-bit does. (Not a useful choice, though:callw
truncates EIP to 16 bits.)Although on the other hand, the default operand size (without a REX.W prefix) for most instructions in 64-bit mode is still 32. But
add $1, (%rdi)
needs an operand-size suffix; the assembler won't pick 32-bit for you if nothing implies one. OTOH,push
is implicitlypushq
, even thoughpushw $1
andpushq $1
are both encodeable (and usable in practice) in 64-bit mode.
From Intel's instruction-set ref manual (linked above):
For a near call absolute, an absolute offset is specified indirectly in a general-purpose register or a memory location (r/m16, r/m32, or r/m64). The operand-size attribute determines the size of the target operand (16, 32 or 64 bits). When in 64-bit mode, the operand size for near call (and all near branches) is forced to 64-bits.
for rel32 ... As with absolute offsets, the operand-size attribute determines the size of the target operand (16, 32, or 64 bits). In 64-bit mode the target operand will always be 64-bits because the operand size is forced to 64-bits for near branches.
In 32-bit mode, you can encode a 16-bit call rel16
that truncates EIP to 16 bits, or a call r/m16
that uses an absolute 16-bit address. But as the manual says, the operand-size is fixed in 64-bit mode.
//------------------------------------------------------问题原始点-------------------------------------------------------//
https://segmentfault.com/q/1010000019148085/a-1020000019199743
请问反汇编代码中callq 23<main+0x13>的含义:
第一个参数我只知道是push 23,保存返回地址,第二个<main+0x19>应该是fun函数地址,但是fun函数应该是在main的前面啊,怎么地址反而比main的地址还高?
C代码:
#include <stdio.h>
void fun(int a)
{
}
int main()
{
int a = 1234;
fun(a);
}
objdump -D main.o main.asm
反汇编代码main.asm如下
0000000000000000 <fun>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 89 7d fc mov %edi,-0x4(%rbp)
7: 90 nop
8: 5d pop %rbp
9: c3 retq
000000000000000a <main>:
a: 55 push %rbp
b: 48 89 e5 mov %rsp,%rbp
e: 48 83 ec 10 sub $0x10,%rsp
12: c7 45 fc 03 00 00 00 movl $0x3,-0x4(%rbp)
19: 8b 45 fc mov -0x4(%rbp),%eax
1c: 89 c7 mov %eax,%edi
1e: e8 00 00 00 00 callq 23 <main+0x19>
23: b8 00 00 00 00 mov $0x0,%eax
28: c9 leaveq
29: c3 retq