1

I'm having a bit of trouble working with .extern variables in assembly. How can I get their value to put into a register?

.extern a, b, c
.global main

.text
main:
  mov *value of a*, %rax
    ret

I've tried the following:

  1. putting sign before a: .a, $a, a[0], a[1], *a
  2. trying to treat .extern as a label .extern+2 etc'
  3. also tried .extern a

I think I don't quite understand what the meaning of .extern is and how to access it. I've tried reading Intel's manual but I couldn't find any information online which regards what I need - I guess I didn't know how to write my question properly since I don't know what .extern is.

If anyone could refer me to information about it and how to use it I would be very grateful.

1201ProgramAlarm
  • 32,384
  • 7
  • 42
  • 56
E. Ginzburg
  • 253
  • 2
  • 9

1 Answers1

2

mov a(%rip), %rax loads from a.

(So would mov a, %rax but don't do that; you always want RIP-relative or an integer register for addressing static storage in x86-64.)

I think what you're missing is that .extern is like in C++: it declares that the symbol is defined elsewhere, in a different object file. So the above would assemble but then not link into an executable unless you linked with another .o e.g. from compiling long a = 1; at global scope in a .c

In GAS .extern is a no-op because that's already assumed for symbol names that aren't defined in the current asm file. See the manual.


Perhaps you wanted to reserve some space in the .data section and put a label on that space, like a C compiler would when you declare a global variable:

long a;
long main(){   // with int main GCC optimizes to loading only EAX
    return a;
}

compiles with GCC -O2 (Godbolt) to the following asm, boiled down to the parts you'd want to keep for a hand-written version:

main:
        mov     a(%rip), %rax
        ret

  .comm   a,8,8    # reserve 8 bytes in the BSS and call it  a

If we'd used long a = 1; (a non-zero initializer):

.data             # switch to the .data section
.globl  a         # declare a as externally visible, like a C global not static
a:                          # a label declares a symbol with address = this position
        .quad   1           # a qword with integer value 1

In general you can learn asm syntax from compiler output if you know what to look for, and compile simple enough C files. (How to remove "noise" from GCC/clang assembly output?) But some of the essential parts (e.g. .section) is mostly noise if you know what to expect so Godbolt filters it out. And to see it you have to also see .size and .type declarations which you don't need to worry about as a beginner.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • thank you very much for all the information and for your help! I think I understand better now. can you perhaps advice me on how to print the content of the register so I can actually see what's going on there? I tried moving %ebx where a stored into %rsi and calling syscall, but it doesn't work – E. Ginzburg Nov 18 '19 at 07:08
  • `write` takes a pointer to a string in memory. `strace` will show you that you get `-EFAULT` for a bad pointer if you pass an integer value. You can convert manually: [Printing an integer as a string with AT&T syntax, with Linux system calls instead of printf](//stackoverflow.com/a/45851398). Or maybe you're looking for printf. [Calling printf in x86\_64 using GNU assembler](//stackoverflow.com/q/38335212) Google would tell you this. Or look at compiler output from C. – Peter Cordes Nov 18 '19 at 07:15