How to set a variable in GCC with Intel syntax inline assembly?
Asked Answered
D

3

17

Why doesn't this code set temp to 1? How do I actually do that?

int temp;
__asm__(
    ".intel_syntax;"
    "mov %0, eax;"
    "mov eax, %1;"
    ".att_syntax;"
    : : "r"(1), "r"(temp) : "eax");
printf("%d\n", temp);
Dallman answered 22/3, 2011 at 20:50 Comment(0)
C
17

You want temp to be an output, not an input, I think. Try:

  __asm__(
      ".intel_syntax;"
      "mov eax, %1;"
      "mov %0, eax;"
      ".att_syntax;"
      : "=r"(temp)
      : "r"(1) 
      : "eax");
Coeternity answered 22/3, 2011 at 21:0 Comment(3)
Oh I can't believe I missed it x___x you're definitely right; that was the problem. Thanks a lot!Dallman
@Mehrdad - I think you need the instructions in the other order, too, now that I look at it. Edited!Coeternity
@Mehrdad - just coincidence. You can check out the output binary for why exactly. On my machine it's reusing the same register for the input and output, so that's how it ended up looking like it worked.Coeternity
N
8

This code does what you are trying to achieve. I hope this helps you:

#include <stdio.h>

int main(void)
{
    /* Compile with C99 */
    int temp=0;

    asm
    (   ".intel_syntax;"
        "mov %0, 1;"
        ".att_syntax;"
        : "=r"(temp)
        :                   /* no input*/
    );
    printf("temp=%d\n", temp);
}
Neuman answered 22/3, 2011 at 21:30 Comment(3)
BTW, to use att_syntax the line would be: asm("mov $1, %0;" : "=r"(temp) :/* no input*/);Neuman
Related: Referencing memory operands in .intel_syntax GNU C inline assembly. If you use a memory output operand, you'll need to compile with -masm=intel.Mcgrody
Thank you for the reference, PeterNeuman
P
5

You have to pass an argument to GCC assembler.

gcc.exe -masm=intel -c Main.c
gcc.exe Main.o -oMain.exe

And you have C code like this:

#include <conio.h>
#include <stdio.h>

int myVar = 0;

int main(int argc, char *argv[])
{
    asm("mov eax, dword ptr fs:[0x18]");
    asm("mov eax, dword ptr ds:[eax+0x30]");
    asm("movzx eax, byte ptr ds:[eax+0x2]");
    asm("mov _myVar, eax");

    if(myVar == 1) printf("This program has been debugged.\r\n");
    printf("Welcome.\r\n");
    getch();

    return 0;
}

Don't forget to add prefix underscore (_) for every variables in asm() keyword, or it won't recognize it.

And keyword asm() use prefix '0x' for every hexadecimal integer, not suffix 'h'.

Petry answered 31/8, 2013 at 3:45 Comment(2)
The header conio.h and getch() are nonstandard, and should be replaced with standard alternatives. This link faq.cprogramming.com/cgi-bin/… shows both standard C and C++ examples of how to do it. It also mentions getch() and other platform-specific methods, but it's better to provide examples that use standard constructs, especially when you don't know what platform the user is running on.Gabrielgabriela
This is syntactically valid, but you're missing constraints on your asm statements so the compiler doesn't know which registers you're using, or that the asm statement modifies the global myVar. If you compiled with optimization, this might easily break. This is an example of how not to use inline asm. It needs to be one single asm statement, preferably with an "=m"(myvar) output. See also gcc.gnu.org/wiki/ConvertBasicAsmToExtendedMcgrody

© 2022 - 2024 — McMap. All rights reserved.