1

(editor's note: this is a debugging question about what's wrong with this attempted implementation (nearly everything), and thus not a duplicate of How to write a short block of inline gnu extended assembly to swap the values of two integer variables? But see that Q&A and https://stackoverflow.com/tags/inline-assembly/info if you want a working example.)


I'm trying to swap two integer variables using gnu extended assembly, here's what I have for now:

int main()
{
    int a = 2;
    int b = 1;
    printf("a is %d, b is %d\n", a, b);
    // TODO (student): swap a and b using inline assembly
    printf("a is %d, b is %d\n", a, b);
    asm ("mov ebx, b;"
        "mov ecx, b;"
        "mov c, ecx;"
        "mov d, ebx;"
    );

I get the error message: asmPractice.c:17: Error: too many memory references for mov.

How do I solve this?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • 2
    Possible duplicate of [asm in C "too many memory references for \`mov'"](https://stackoverflow.com/questions/15035379/asm-in-c-too-many-memory-references-for-mov) – Conrad Parker Aug 31 '17 at 04:28
  • You can used `XCHG` instruction on x86 for swapping. – Milind Deore Aug 31 '17 at 04:28
  • 2
    Seems like someone had the same assignment here on this SO question. https://stackoverflow.com/q/45910530/3857942 . You can't use variable names the way you are reliably (or at all). You have to use extended inline passing the parameters through constraints. The answer to that other SO question should give you an idea why you should avoid GNU inline assembly unless you know what you are doing. If using AT&T syntax the operands are reversed compared to Intel syntax. – Michael Petch Aug 31 '17 at 04:38
  • @AnttiHaapala : it is tagged GNU and C (and GNU assembly) so one can at least assume GCC. Platform is suggested by the assembly instructions which appear to be x86. – Michael Petch Aug 31 '17 at 04:43
  • Wendi you say that you're unable to compile after fixes; can you ensure you an compile the program *without* inline assembler? – Antti Haapala -- Слава Україні Aug 31 '17 at 04:57
  • i can compile without inline assembler. after putting % before registers, i get: undefined reference to `a' and undefined reference to `b' – Wendi Zhang Aug 31 '17 at 16:30

3 Answers3

3

Using extended inline assembly syntax, this is a one-liner:

volatile int a = 1;
volatile int b = 2;

asm("" : "=r" (a), "=r" (b) : "0" (b), "1" (a) : );
//      ^^^^^^^^^^^^^^^^^^   ^^^^^^^^^^^^^^^^^
//           input               output

printf("a is %d, b is %d\n", a, b);
Andreas DM
  • 10,685
  • 6
  • 35
  • 62
0

Don't know if it matters. But in my remember, you need to put % before register call in order to make the interpreter understand you speak about register. Like mov %esp, %ebp

Try it but not 100% sure will fix it. asm in C "too many memory references for `mov'" refering to this post

Brighter side
  • 392
  • 2
  • 14
  • I've tried that before, but it gives the error: /usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/5/libgcc.a when searching for -lgcc /usr/bin/ld: cannot find -lgcc – Wendi Zhang Aug 31 '17 at 04:45
  • @WendiZhang that is the correct correction, and that is now another problem. – Antti Haapala -- Слава Україні Aug 31 '17 at 04:49
  • @WendiZhang : You'll get that error if you are compiling on 64-bit linux without the gcc-multilib package. If you are on Ubuntu (or ubuntu based distro) you could try `sudo apt install gcc-multilib` or on Debian `apt install gcc-multilib` . Then compile using `gcc` and the `-m32` option. – Michael Petch Aug 31 '17 at 04:49
-1

Try put double % before register.

Edil
  • 14
  • 1
  • 1
    That's necessary but not sufficient for 2 reasons: 1) It's still AT&T syntax, so `mov src,dst`. 2) The variables are locals, not static storage, so `a` and `b` aren't valid symbol names in asm. You need to use Extended Asm input/output constraints to access them. See the OP's last comment under the question. – Peter Cordes Feb 23 '19 at 06:03
  • 1
    Anyway, [How to write a short block of inline gnu extended assembly to swap the values of two integer variables?](//stackoverflow.com/q/45910530) already has a working version. – Peter Cordes Feb 23 '19 at 06:05