-4

The fallowing program must print 3 , but 'buff' is not seen from asm.

#include <stdio.h>

char buff[] = "%d\n";

int main (void)
{
    asm("mov eax, 3");
    asm("mov esi,eax");
    asm("mov edi,buff");
    asm("mov eax, 0");
    asm("call printf");
   return 0;
}

I try to use the asm intel syntax . it compile with : gcc -masm=intel -o test2 test2.c

The line

asm("mov edi,buff");

Is wrong , how do i must to write the buff here? I tried [buff] but do not works.Thank you

**Update:

next program works , BUT is using AT&T syntax :

#include <stdio.h>

char Format[] = "%d\n";

int main (void)
{
   asm
   (
      // Make stack space for arguments to printf
      "movl $3, %eax\n"
      "movl %eax, %esi\n"
      "movl $Format, %edi\n"
      "movl $0, %eax\n"
      "call printf\n"

   );
   return 0;
}  //compile with gcc -o test2 test2.c

I try to do same using intel syntax , but I do not know how to access the global variable ,from asm corectly

CGeorgian
  • 551
  • 6
  • 10
  • 1
    It's hard to know where to start telling you what's wrong. The #1 point is probably: Don't use inline asm (see https://gcc.gnu.org/wiki/DontUseInlineAsm). #2: Don't use multiple inline asm lines, use 1 statement with multiple instructions. #3: Don't access C variables from 'basic' asm, use the constraints from [extended asm](https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html). #4: Calling functions from inline asm is VERY tricky and probably doomed. #5: What makes you think this will print '5' instead of (say) '3'? There's probably more, but this is just a bad implementation of a bad idea. – David Wohlferd Aug 26 '16 at 02:26
  • 1
    @DavidWohlferd It looks like this is an exercise to learn inline asm. – user253751 Aug 26 '16 at 02:35
  • Yes I'm doing tests, how to use asm from c code, I updated the question ,Yes , it must print 3 , was just a wrong typing . I put the working asm code that works using AT&T syntax , but I try do the same using intel syntax – CGeorgian Aug 26 '16 at 02:36
  • 1
    The [x86 tag wiki](http://stackoverflow.com/tags/x86/info) has some links. Specifically, see the links at the bottom of [this answer](http://stackoverflow.com/questions/34520013/using-base-pointer-register-in-c-inline-asm/34522750#34522750), especially the tutorial. And read that answer to learn why **inline asm is the *hardest* way to learn assembly**. Write whole functions in asm and call them from C. Also note that using `call` from inside a GNU C inline asm statement isn't safe, because you can't tell the compiler you want to clobber the red-zone, as that answer explains. – Peter Cordes Aug 26 '16 at 02:39
  • You right , but I was just curious how to translate this , from AT&T syntax into Intel syntax. I just think the problem is , that i'm missing some '[' or '(' .or '%' signs. I did not belived is so hard to tarnslate a so simple example – CGeorgian Aug 26 '16 at 02:50
  • If you really must... Try writing `printf(Format, 3);` and compile it with `gcc -S test2.c`. This will generate test2.s, which contains the asm code gcc generated to do the call. Also note that since you are still using 'basic' asm (instead of extended), gcc cannot see that you are using `Format` anywhere (from the docs: *GCC does not parse the assembler instructions themselves and does not know what they mean or even whether they are valid assembler input*). As a result, if you enable any optimizations (-O2), it will probably discard Format from the output as 'unused.' – David Wohlferd Aug 26 '16 at 03:06
  • @DavidWohlferd: only `static` unused globals actually get discarded. See [this comment thread](http://stackoverflow.com/a/38741832/224132) and the gcc (non-)bug report mentioned in that answer. IDK if a more sophisticated GNU C compiler would be allowed to discard it, but I suspect not because it might be a symbol that a library expects to find. – Peter Cordes Aug 26 '16 at 03:13
  • @David Wohlferd I'm not a pro at asm , but I think "GCC does not parse the assembler instructions themselves and does not know what they mean or even whether they are valid assembler input" is very WRONG , or was valid for old gcc .I say this because when I did asm test , I receive a lot of erros from GCC when my asm code is not right – CGeorgian Aug 26 '16 at 03:20
  • @DionisL: those messages were from the assembler, not the compiler. – Peter Cordes Aug 26 '16 at 03:50
  • 1
    @PeterCordes: Sure enough `-O2` is not enough to get this discarded. But `-fwhole-program` does. – David Wohlferd Aug 26 '16 at 04:15

1 Answers1

0

As @Peter Cordes said to me i read at https://stackoverflow.com/tags/x86/info about OFFSET keyword , and now it works. I knew the problem is i put in registry a data ,and not a address ,and looks like OFFSET keyword was what I was searching for .

Wrorking one is :

#include <stdio.h>

char buff[] = "%d\n";

int main (void)
{
    asm("mov eax, 3");
    asm("mov esi,eax");
    asm("mov edi,OFFSET buff");
    asm("mov eax, 0");
    asm("call printf");
   return 0;
}
Community
  • 1
  • 1
CGeorgian
  • 551
  • 6
  • 10
  • It's only working if you compile with `gcc -masm=intel -mno-red-zone`. Then it probably works as long as the compiler doesn't insert anything between your separate asm statements. You could also have just used a constraint to tell the compiler you wanted `buff` in edi. IIRC, the syntax is `asm("call printf" : : "a"(0), "S"(3), "D"(buff) : "memory", "rcx", "rdx", "r8", "r9", "r10", "r11", "xmm0", "xmm1", ... "xmm15");` (You have to tell the compiler when you clobber a register, and you have to assume a function call clobbers all the non-call-preserved registers) – Peter Cordes Aug 26 '16 at 03:06
  • The code in my last comment might actually be safe if in general (i.e. with any surrounding code) if compiled with `-mno-red-zone`. Oh, I guess you technically also need to declare clobbers on the FP stack registers, since printf could clobber them, too. Also, IDK why you don't just use `mov esi, 3`. You know you don't need the 3 in eax, since you zero it later (since printf is a var-args function and you're passing 0 FP args in xmm regs). – Peter Cordes Aug 26 '16 at 03:10
  • Thanks for help . What was trying to do was , that I had a simple binary of a program that did a printf("%d\n",3) and I was dessansambled this binary ,and I tried to see if I can put the asm instructions from this binary into a C program .After this was done using AT&T , I tried to see if is any difference between that binary and my new program binary .They looks same. – CGeorgian Aug 26 '16 at 03:12
  • You can compile with `-S -masm=intel`, or use `objdump -Mintel` to dump in GNU C Intel syntax in the first place. But in general no, this isn't a safe thing to do. If you included that code as part of a larger program, the function it's in could still be inlined, and then you'd be stepping on the values in registers the compiler-generated code is expecting. **Your code works, but only because you got lucky in this simple case, *not* because it's correct bug-free code.** If you want to play with compiler output, put it in a `.S` and edit that. – Peter Cordes Aug 26 '16 at 03:17
  • You want to say is not indicated to use asm in C code ,or is not indicated to access C variables from asm ,in a C code ? Cause I see kernel also is using asm from C code.If I write a C fucntion taht contains only asm code , and I call this function from the C code , is better?Thank you – CGeorgian Aug 26 '16 at 03:25
  • The people that wrote Linux's inline-asm macros and wrapper functions understand C, asm, and the GNU C inline asm syntax that lets the compiler and hand-written asm interact safely with low overhead. It can be hard to get it correct, so only worth doing when necessary (e.g. for privileged instructions the compiler won't emit). You don't understand asm or GNU C inline asm syntax (yet), so you should just write whole functions in asm and call them from C, like I explained in [this answer](http://stackoverflow.com/questions/34520013/using-base-pointer-register-in-c-inline-asm/34522750#34522750). – Peter Cordes Aug 26 '16 at 03:30
  • Thank you .In fact , I have a binary (without source code ) .I need to build some asm code , that I want to inject into this binary , My asm code needs to printf ,some data this binary have.So i needed C a program in witch I test this asm code ,if works or not.So I'm using a C program that test if the asm code I need to inject works or not.I'm still doing tests ...... – CGeorgian Aug 26 '16 at 03:41
  • If you want the program to keep working after running the code you inject, you have to avoid destroying its registers or memory (and this time you don't have the option of compiling with `-mno-red-zone`). See [Michael Petch's answer about calling printf from inline asm](http://stackoverflow.com/questions/37502841/calling-printf-in-extended-inline-asm) for an idea of what kind of stuff you might have to do. – Peter Cordes Aug 26 '16 at 03:49
  • This binary ,have a function ,this functions returns the data i want to printf from eax register , now i have to see if after a printf , eax still keeps the same value , so the bianry to continue working. – CGeorgian Aug 26 '16 at 03:57
  • Of course it won't. printf's return value will be in `eax`. Why don't you just use a debugger and set a breakpoint and print eax there, instead of trying to modify the binary? That would be *way* easier. You should be able to get a debugger like `gdb` to `print /x $eax` and then continue executing, so you don't have to manually continue every time. – Peter Cordes Aug 26 '16 at 04:11