1

I'm writing a compiler for a class, and I'm stuck on GNU's syntax for doing indirect call. Consider this simple program:

.text
.globl main
main:
  movl func, %eax
  call *%eax
  ret

func:
  movl $42, %eax
  ret

Compiling with gcc -m32 -O0 and running the resulting program gives me a segmentation fault. Can anyone tell me how to do the call correctly?

Thanks.

Vincent.

Daniel Kamil Kozar
  • 18,476
  • 5
  • 50
  • 64
gnuvince
  • 2,357
  • 20
  • 27
  • Related question: http://stackoverflow.com/questions/1897401/gnu-assembler-get-address-of-label-variable-intel-syntax – clstrfsck Apr 16 '12 at 00:43

2 Answers2

6

The call instruction itself is actually good. :)

Your problem is that you seem to forget how the AT&T syntax works. What you're doing right here with movl func, %eax is copying a dword from the address of the label func to the eax register. Essentially, eax ends up with the first 4 bytes of actual code of your function.

Immediate operands in AT&T are prefixed with a $. The value of the func label, being a compile-time constant can be used as an immediate and that's what you want in this case. Therefore, replace movl func, %eax with movl $func, %eax and you'll be alright. :)

Using lea here is redundant. It will work, of course, but since func is a compile-time constant, it's much more effective to simply put it as an immediate in the code instead of figuring it out at runtime.

Daniel Kamil Kozar
  • 18,476
  • 5
  • 50
  • 64
-3

I think I got it; using leainstead of movl fixed the problem; I imagine that lea does virtual address translation.

gnuvince
  • 2,357
  • 20
  • 27
  • 2
    Nonsense. This has nothing to do with virtual addresses. `lea` loads the effective address of the label func into eax, while mov loads the content of the label at func, which are the opcodes of `mov $42, %eax` and do not make any sense if interpreted as address. – Gunther Piez Apr 16 '12 at 07:56