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);
Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
user541686
  • 205,094
  • 128
  • 528
  • 886

3 Answers3

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");
Carl Norum
  • 219,201
  • 40
  • 422
  • 469
  • Oh I can't believe I missed it x___x you're definitely right; that was the problem. Thanks a lot! – user541686 Mar 22 '11 at 21:01
  • @Mehrdad - I think you need the instructions in the other order, too, now that I look at it. Edited! – Carl Norum Mar 22 '11 at 21:12
  • @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. – Carl Norum Mar 22 '11 at 21:15
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);
}
DrBeco
  • 11,237
  • 9
  • 59
  • 76
  • BTW, to use att_syntax the line would be: `asm("mov $1, %0;" : "=r"(temp) :/* no input*/);` – DrBeco Mar 23 '11 at 00:09
  • 2
    Related: [Referencing memory operands in .intel\_syntax GNU C inline assembly](https://stackoverflow.com/q/51905409). If you use a memory output operand, you'll need to compile with `-masm=intel`. – Peter Cordes Aug 18 '18 at 06:39
  • Thank you for the reference, Peter – DrBeco Aug 18 '18 at 20:43
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'.

Al Man Afaron
  • 91
  • 1
  • 1
  • 1
    The header conio.h and getch() are nonstandard, and should be replaced with standard alternatives. This link http://faq.cprogramming.com/cgi-bin/smartfaq.cgi?answer=1042856625&id=1043284385 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. – Elkvis Jul 21 '15 at 17:24
  • 1
    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 https://gcc.gnu.org/wiki/ConvertBasicAsmToExtended – Peter Cordes Oct 05 '20 at 00:13