Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use a global variable in gcc inline assembly

I am trying to use inline assembly like this, for a global variable, but the compiler gives an error by saying undefined reference to saved_sp.

__asm__ __volatile__ (
        "movq saved_sp, %rsp\n\t" );

saved_sp is declared as static long saved_sp globally (for a file that is). What mistake am I doing here?

like image 602
MetallicPriest Avatar asked Jan 10 '12 20:01

MetallicPriest


2 Answers

If it fails with "undefined reference to `saved_sp' " (which is really a linker error, not a compiler error) when saved_sp is static, but works when it is not, then it seems likely that the compiler has decided that saved_sp is not used in your source file, and has therefore decided to omit it completely from the compiled code that is passed to the assembler.

The compiler does not understand the assembly code inside the asm block; it just pastes it into the assembly code that it generates. So it does not know that the asm block references saved_sp, and if nothing else in the C code ever reads from it, it is at liberty to decide that it is completely unused - particularly if you have any optimisation options enabled.

You can tell gcc that saved_sp is used by something that it can't see, and therefore prevent it from choosing to throw it away, by adding the used attribute (see the documentation of variable attributes, about half-way down the page), e.g.:

static long __attribute__((used)) saved_sp;

Here's a fully worked example:

$ cat test.c
#ifdef FIXED
static long __attribute__((used)) saved_sp;
#else
static long saved_sp;
#endif

int main(void)
{
  __asm__ __volatile__ (
        "movq saved_sp, %rsp\n\t" );
}

$ gcc -m64 -o test test.c
$ gcc -m64 -O1 -o test test.c
/tmp/ccATLdiQ.o: In function `main':
test.c:(.text+0x4): undefined reference to `saved_sp'
collect2: ld returned 1 exit status
$ gcc -m64 -DFIXED -O1 -o test test.c
$ 

(This is from a 32-bit Debian squeeze system with gcc 4.4.5, which is the closest thing I have to hand; -m64 may well be unnecessary on your system.)

like image 173
Matthew Slattery Avatar answered Nov 13 '22 07:11

Matthew Slattery


Preferably you would use input and output parameters:

__asm__ __volatile__ ( 
    "movq %0, %%rsp\n\t"
    : : "r"(saved_sp) : "memory"
);

Often there can be some variables that are not symbols at all at the assembling stage (for example stack variables, or registers. Also, you'd want to clobber the whole memory, to ensure that no stack variables are kept in register after the saved_sp is stored in RSP.