1

I'm trying to compile following asm code inside a C++ file, but it like GCC can't find the variables used in the asm part.

DWORD d_eaxSave, d_ebxSave, d_ecxSave, d_edxSave, d_esiSave, d_ediSave, d_espSave, d_ebpSave;

#define ASM_UNPREFIXED_INTEL_START ".intel_syntax noprefix\n\t"
#define SAVE_REGISTERS() __asm__ (ASM_UNPREFIXED_INTEL_START    \
                              "mov d_eaxSave, eax\n\t"      \
                              "mov d_ebxSave, ebx\n\t"      \
                              "mov d_ecxSave, ecx\n\t"      \
                              "mov d_edxSave, edx\n\t"      \
                              "mov d_esiSave, esi\n\t"      \
                              "mov d_ediSave, edi\n\t"      \
                              "mov d_espSave, esp\n\t"      \
                              "mov d_ebpSave, ebp");

But when I try to compile, GCC gives me the following errors :

undefined reference to `d_eaxSave'
undefined reference to `d_ebxSave'
undefined reference to `d_ecxSave'
undefined reference to `d_edxSave'
undefined reference to `d_esiSave'
undefined reference to `d_ediSave'
undefined reference to `d_espSave'
undefined reference to `d_ebpSave'

What can I do to get rid of those erros, please ?

kranium632
  • 45
  • 1
  • 7

1 Answers1

3

You want to generally use the AT&T syntax, because as far as I know, GCC cannot emit proper intel syntax in inline assembler without -masm=intel command line switch for everything - I'd presume then you cannot include any header files that would use AT&T inline assembly.

Thus:

DWORD d_eaxSave, d_ebxSave, d_ecxSave, d_edxSave, d_esiSave, d_ediSave, d_espSave, d_ebpSave;

#define SAVE_REGISTERS() __asm__ __volatile__(         \
     "movl %%eax, %0\n\t"      \
     "movl %%ebx, %1\n\t"      \
     "movl %%ecx, %2\n\t"      \
     "movl %%edx, %3\n\t"      \
     "movl %%esi, %4\n\t"      \
     "movl %%edi, %5\n\t"      \
     "movl %%esp, %6\n\t"      \
     "movl %%ebp, %7":         \
     "=m"(d_eaxSave), "=m"(d_ebxSave), "=m"(d_ecxSave), "=m"(d_edxSave),  \
     "=m"(d_esiSave), "=m"(d_ediSave), "=m"(d_espSave), "=m"(d_ebpSave)   \
)

The symbols might not exist for the assembler, so you need to use them via output parameters! Note also, that generally you would want to use __volatile__ to make sure that the assembler block is not optimized away.

Community
  • 1
  • 1
  • That why the OP has a `.intel_syntax noprefix` directive, but he probably needs to add a `.att_syntax prefix` at the end to set it back. But that's independent of using the output parameters which is the real (and correct) answer to the question. – Chris Dodd Jul 30 '14 at 16:58
  • Nope, the `.intel_syntax noprefix` did not make GCC emit Intel syntax output parameters; and if the whole file needs to be compiled using `.intel_syntax` anyways, there is no point in changing the syntaxes. Also if this is in a header file, it will cause a major nuisance if any other files with inline assembler are used. – Antti Haapala -- Слава Україні Jul 30 '14 at 17:04
  • 1
    This is the way to go (except that I would omit the trailing semicolon). Unfortunately, you need a doctorate in compiler architecture to use the GCC in-line assembler with any confidence. – TonyK Jul 30 '14 at 18:18
  • Removed the semicolon; I do not have a doctorate, nor a CS degree of any kind, so I do not have that much confidence, but I did write a 32-bit protected mode kernel in C++ and inline GAS, and the kernel even occasionally works, so. – Antti Haapala -- Слава Україні Jul 30 '14 at 19:36