5

I'm new to assembly in C, and i dont know how to fix this error. I'm making a function that means to write a file. What I have is:

ssize_t mywrite(int fd, const void *buf, size_t count) {
//  return write(fd, buf, count);
    ssize_t var;
    __asm__("movl $4,%%eax\n\t"  // Write
        "movl %1,%%ebx\n\t"
        "movl %2,%%ecx\n\t"
        "movl %3,%%edx\n\t"
        "int  $0x80\n\t"         // System call
        "movl %%eax,%0"
        :"=r"(var)
        :"r"(fd),"r"(buf),"r"(count)
        :"%eax","%ebx","%ecx","%edx"
    );
    return var;
}

My asm is supposed to do the same as write(fd,buf,count); When I compile it, I get "'asm' operand has impossible constraints". However, if don't name the variables and get the values directly from the stack, I get no error. Here's the code

    __asm__("movl $4,%%eax\n\t"
        "movl 8(%%ebp),%%ebx\n\t"
        "movl 12(%%ebp),%%ecx\n\t"
        "movl 16(%%ebp),%%edx\n\t"
        "int  $0x80\n\t"
        "movl %%eax,%0"
        :"=r"(var)
        :
        :"%eax","%ebx","%ecx","%edx"
    );

I could use the second code, ofc, but I need it compiled with optimization 2. Then %ebp won't point where I need it to. I tried using "a", "b", "c" and "d" instead of "r", but no success. Anyone could help? Thanks :D

Behnken
  • 86
  • 5

1 Answers1

7

The problem is that the constraint r means register, but your CPU simply doesn't have so many registers!

You can use the memory constraint m:

:"m"(fd),"m"(buf),"m"(count)

That will generate instructions such as:

movl 8(%ebp),%ebx

But I would recommend to use the x86 constraints in all its glory:

ssize_t mywrite(int fd, const void *buf, size_t count) {
    ssize_t var;
    __asm__(
        "int  $0x80"
        :"=a"(var)
        :"0"(4), "b"(fd),"c"(buf),"d"(count)
    );
    return var;
}

That, with -Ofast gives:

push   %ebx
mov    $0x4,%eax
mov    0x10(%esp),%edx
mov    0xc(%esp),%ecx
mov    0x8(%esp),%ebx
int    $0x80
pop    %ebx
ret

And with -Os:

push   %ebp
mov    $0x4,%eax
mov    %esp,%ebp
push   %ebx
mov    0x10(%ebp),%edx
mov    0x8(%ebp),%ebx
mov    0xc(%ebp),%ecx
int    $0x80
pop    %ebx
pop    %ebp
ret    

Note how, thanks to the use of constraints instead of the registers by name, the compiler is able to optimize the code further.

rodrigo
  • 94,151
  • 12
  • 143
  • 190
  • I tried the x86 constraints and it's working now! Thank you very much! Great to know this alternative way :D – Behnken Jan 26 '16 at 00:00
  • 1
    @Behnken: note that the load-directly-from-the-stack way (2nd way in your question) will break as soon as your function is inlined. So that way isn't even an alternative, it's just broken. (oh I think you knew that, based on the text). The first way in your question would have generated code that loaded data into other registers, then ran your reg-reg move instructions, so it would take twice as many instructions as needed. As always, write as few asm instructions yourself as possible, leaving it up to the compiler to choose how to get data into/out of your inline asm. – Peter Cordes Jan 26 '16 at 08:53
  • @PeterCordes Oh, that's true... I didn't realize that that way was actually broken at first sight. Thanks :D Interesting to note that the code is better optimized this way. As I said, I'm very new to asm, starting to learn, tbh. This is an advice I'll take with me. Thanks for giving it! – Behnken Jan 27 '16 at 00:39
  • @rodrigo Great to note that the compiler is able to optimize better the code. I'll take this way as the main way to do asm for now on. Thanks for all the info! ^-^ – Behnken Jan 27 '16 at 00:43
  • @Behnken: If you're trying to actually learn ASM in general, [inline asm is the hardest way](http://stackoverflow.com/questions/34520013/using-base-pointer-register-in-c-inline-asm). Write whole functions in asm, and call them from C. See also the other links at http://stackoverflow.com/tags/x86/info. Writing correct GNU C inline asm statements requires a good understanding of asm, *and* of what C compilers need to know to optimize around your asm statement (treating it as an opaque inline function described by the constraints). – Peter Cordes Jan 27 '16 at 02:34