|
Rosalee38
|
 |
« Reply #1 on: November 25, 2011, 12:09:53 pm » |
|
Well, you don't say specifically, but by your post, it appears like you're using gcc and its inline asm with constraints syntax (other C compilers have very different inline syntax). That said, you probably need to use AT&T assembler syntax rather than Intel, as that's what gets used with gcc. So with the above said, lets look at your write2 function. First, you don't want to create a stack frame, as gcc will create one, so if you create one in the asm code, you'll end up with two frames, and things will probably get very confused. Second, since gcc is laying out the stack frame, you can't access vars with "[ebp + offset]" ad you don't know how its being laid out. That's what the constraints are for -- you say what kind of place you want gcc to put the value (any register, memory, specific register) and the use "%X" in the asm code. Finally, if you use explicit registers in the asm code, you need to list them in the 3rd section (after the input constraints) so gcc knows you are using them. Otherwise it might put some important value in one of those registers, and you'd clobber that value. So with all that, your write2 function looks like: void write2(char *str, int len) { __asm__ volatile ( "movl $4, %%eax;" "movl $1, %%ebx;" "movl %0, %%ecx;" "movl %1, %%edx;" "int $0x80" :: "g" (str), "g" (len) : "eax", "ebx", "ecx", "edx"); }
Note the AT&T syntax -- src, dest rather than dest, src and % before the register name. Now this will work, but its inefficient as it will contain lots of extra movs. In general, you should NEVER use mov instructions or explicit registers in asm code, as you're much better off using constraints to say where you want things and let the compiler ensure that they're there. That way, the optimizer can probably get rid of most of the movs, particularly if it inlines the function (which it will do if you specify -O3). Conveniently, the i386 machine model has constraints for specific registers, so you can instead do: void write2(char *str, int len) { __asm__ volatile ( "movl $4, %%eax;" "movl $1, %%ebx;" "int $0x80" :: "c" (str), /* c constraint tells the compiler to put str in ecx */ "d" (len) /* d constraint tells the compiler to put len in edx */ : "eax", "ebx"); }
or even better void write2(char *str, int len) { __asm__ volatile ("int $0x80" :: "a" (4), "b" (1), "c" (str), "d" (len)); }
Note also the use of volatile which is needed to tell the compiler that this can't be eliminated as dead even though its outputs (of which there are none) are not used.
|