Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Warning: indirect call without `*'

Having this simple assembly:

.text
    .globl main
str:
    .asciz "%i\n"
add:
    push %rbp
    mov %rsp, %rbp
    movl %esi, %eax
    addl %edi, %eax
    pop %rbp
    ret

main:
    mov $1, %esi
    mov $2, %edi
    lea add(%rip), %rax
    call %rax #what is wrong here? the rax should contain first instruction of add
    mov %eax, %esi
    xor %eax, %eax
    lea str(%rip), %rdi
    call printf
    xor %eax, %eax
    ret

I am getting error:

foo.s:17: Warning: indirect call without `*'

Why? The %rax should contain the address of function (as denoted in comment), and this is not c, where there are pointer with *, but register that contains an address. So what is wrong here?

like image 595
milanHrabos Avatar asked Dec 10 '25 07:12

milanHrabos


2 Answers

Change

call %rax

to

call *%rax

This is not the same as call *(%rax). From @interjay's comment below:

call *%rax calls the address stored in rax (which is what OP wants to do), while call *(%rax) calls the address stored in memory pointed to by rax

The asterisk indicates that the call is an indirect call. It means call function stored inside %rax

like image 151
Waqar Avatar answered Dec 12 '25 22:12

Waqar


AT&T syntax always requires a * on indirect calls, like call *%rax. This sets RIP = RAX.
call *(%rax, %rdi) would load from memory like RIP = mem_load(RDI+RAX).
call *foo(%rip) would load a new RIP from memory at the address foo, using a RIP-relative addressing mode.

When it's missing a * but still unambiguously an indirect call (because of a register operand or a (%reg) addressing mode), the assembler will infer that and warn you about it.


That AT&T syntax design avoids ambiguity between call foo (direct) and call *foo (memory indirect with an absolute-direct addressing mode).

Normally in 64-bit mode you'd use call *foo(%rip), but the ambiguity would still exist if call foo could mean memory indirect. And of course the syntax was designed before AMD64 existed.

In Intel syntax, memory-indirect call that loads a pointer into EIP/RIP from memory at the address foo with absolute addressing would be:

  • GAS Intel syntax: call [foo], call qword ptr foo, or call ds:foo

  • MASM: call [foo] might ignore the brackets so only qword ptr or ds: work.

  • NASM: call [foo] or call qword [foo]

So as you can see, MASM-style Intel-syntax (as used by GAS .intel_syntax noprefix) uses ds: or qword ptr to indicate that something is a memory operand, allowing call foo to be a normal E8 rel32 call direct.

Of course, as I said, in 64-bit mode you'd normally want to use call [RIP + foo] in GAS or call [rel foo] in NASM. (In actual MASM, I think RIP-relative is on by default.)

like image 33
Peter Cordes Avatar answered Dec 12 '25 22:12

Peter Cordes



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!