| Register | FAQ | Calendar | Search | Today's Posts | Mark Forums Read |
|
#1
| |||
| |||
| Hello all, I have a little piece of inline ASM in my program, and I am missing something when integrating it in my C code. This is the function (that could be a simple #define too) inline void my_function ( unsigned int *C, unsigned char T ) { __asm__ ( "movb $4, %%cl\n\t" \ "and %%al, %%cl\n\t" \ "shr $3, %%al\n\t" \ "movb $240,%%dh\n\t" \ "shr %%cl, %%dh\n\t" \ "andb (%%eax), %%dh\n\t" \ "shl %%cl, %%dl\n\t" \ "or %%dl, %%dh\n\t" \ "movb %%dh, (%%eax)" \ : "=a"(C) : "a" (C), "d" (T) : "cc", "ecx" ) ; } The key-point is the last line of the asm( ) statement. ========================================= IF the last line is the one present: : "=a"(C) : "a" (C), "d" (T) : "cc", "ecx" ) ; gcc generates this as the function code: ..globl my_function .type my_function, @function set_vs_var_typeC4_2: pushl %ebp movl %esp, %ebp popl %ebp ret .size my_function, .-my_function .p2align 4,,15 the inline code is nothing ========================================= IF the last line is: : : "a" (C), "d" (T) : "cc", "ecx" ) ; that is, no output is present, gcc generates this as the function ..globl my_function .type my_function, @function my_function: pushl %ebp movl %esp, %ebp movzbl 12(%ebp), %edx movl 8(%ebp), %eax #APP # 194 "performance_text1.c" 1 movb $4, %cl and %al, %cl shr $3, %al movb $240,%dh shr %cl, %dh andb (%eax), %dh shl %cl, %dl or %dl, %dh movb %dh, (%eax) # 0 "" 2 #NO_APP popl %ebp ret .size my_function, .-my_function .p2align 4,,15 what makes me wonder why the registers eax, edx and ecx are not saved/restored (pushed/popped) as this as inlined: leal -980(%ebp), %ecx movl %ecx, %eax ..L43: #APP <----------- beginning of my code movb $4, %cl and %al, %cl shr $3, %al movb $240,%dh shr %cl, %dh andb (%eax), %dh shl %cl, %dl or %dl, %dh movb %dh, (%eax) #NO_APP <---- end of my code addl $4, %eax cmpl %esi, %eax movl %eax, -1076(%ebp) as the register eax is used by gcc and my code modifies it, the crash is assured. ========================================= IF the last line is: : : "a" (C), "d" (T) : "cc", "ecx", "eax", "edx" ) ; I get a compilation error: error: can't find a register in class ‘AREG’ while reloading ‘asm’ ‘asm’ operand has impossible constraints This all makes me very confuse, can anyone put some light in my path? what should appear in the last line? why gcc does not take care of saving the input parameters? Thanks a lot in advance, David |
|
#2
| |||
| |||
| The clobber list tells gcc which registers (or memory) are changed by the asm, but not listed as an output. That way, gcc knows not to leave a value in there and expect it to be the same after the asm. If you clobber enough registers, gcc has to start saving values on the stack instead of in unclobbered registers. You already list eax as an output, you don't need to list it in the clobber, and in fact get an error if you do (you're telling gcc that you need two eax registers if you do). You can overlap clobbers and *input* registers. If gcc determines that the outputs of your asm aren't needed, it may omit the asm completely. Use "volatile" if you want it to stay no matter what (i.e. asm volatile (...)). An asm with no output is probably assumed to be volatile (else why else would you have put it there?) as is an asm with *no* parameters (just the opcode string). Clobbered registers need not be preserved by gcc if gcc has no need to preserve whatever value was in them before the asm anyway. |
|
#3
| |||
| |||
| On Aug 15, 11:17 pm, DJ Delorie <d...@delorie.com> wrote: Thanks for the explanation .> You can overlap clobbers and *input* registers. Then, why gcc complains if I put this __asm__ ( "movb $4, %%cl\n\t" \ "andb %%al, %%cl\n\t" \ "movb %%al, %%ch\n\t" \ "shrb $3, %%al\n\t" \ "movb $240,%%dh\n\t" \ "shrb %%cl, %%dh\n\t" \ "andb (%%eax), %%dh\n\t" \ "shlb %%cl, %%dl\n\t" \ "orb %%dl, %%dh\n\t" \ "movb %%dh, (%%eax)\n\t" \ "movb %%ch, %%al\n\t" \ : : "a" (C), "d" (T) : "cc", "ecx", "edx" ) ; (I am trying to tell gcc: eax and edx are input, but I modify eax, edx and ecx) saying that could'nt find a register in DREG class while reloading asm? (I dont think the gcc error message could be more cryptic ).What I would really like to put is : : "a" (C), "d" (T) : "cc", "ecx", "edx", "eax" ) ; but gcc is a "complainer"!! grrr |
|
#4
| |||
| |||
| ditiem wrote: > What I would really like to put is > > : : "a" (C), "d" (T) : "cc", "ecx", "edx", "eax" ) ; > > but gcc is a "complainer"!! grrr > registers used as input or output operands must have no part mentioned in the clobber description. So you can only leave "cc" and "ecx" in your clobber list. please refer to: $ info gcc 'c ext' 'ext asm' for details. |
|
#5
| |||
| |||
| Jike Song wrote: > ditiem wrote: >> What I would really like to put is >> >> : : "a" (C), "d" (T) : "cc", "ecx", "edx", "eax" ) ; >> >> but gcc is a "complainer"!! grrr >> > > registers used as input or output operands must have no part mentioned > in the clobber description. So you can only leave "cc" and "ecx" in > your clobber list. > The way to denote an input register which also gets clobbered is with a input/output operand: : "=d" (junk) : "a" (C), "d" (T) : "cc", "ecx"); The gcc developers don't seem to have any interest in cleaning up this particular syntactic wart. -hpa |
|
#6
| |||
| |||
| H. Peter Anvin wrote: > > The way to denote an input register which also gets clobbered is with a > input/output operand: > > : "=d" (junk) : "a" (C), "d" (T) : "cc", "ecx"); Sorry Peter, I missed your point here. Do you mean that being an input operand is still not informative enough to tell gcc that edx is clobbered? I previously take it for granted that gcc will make sure all input/output operands could be clobbered and will take care of them. > > The gcc developers don't seem to have any interest in cleaning up this > particular syntactic wart. > > -hpa And the inline asm is still not well documented... |
|
#7
| |||
| |||
| > I previously take it for granted that gcc will make sure all input/output > operands could be clobbered and will take care of them. This is not true. All the output operands are clobbered, but the inputs are not. In fact, it happens that in my case an input was a pointer that gcc expected to be unaltered after my asm code, so it reused after inlining the asm code, generating a segmentation fault. Even further, I have found out that gcc complains or not depending on the optimization level (after -O2) that you select. The input, output and clobber lists are clear but in practice there are not so clear and the messages are very cryptic. |
|
#8
| |||
| |||
| Jike Song wrote: > H. Peter Anvin wrote: >> >> The way to denote an input register which also gets clobbered is with >> a input/output operand: >> >> : "=d" (junk) : "a" (C), "d" (T) : "cc", "ecx"); > Sorry Peter, I missed your point here. Do you mean that being an input > operand is still not informative enough to tell gcc that edx is clobbered? > > I previously take it for granted that gcc will make sure all input/output > operands could be clobbered and will take care of them. Input operands are *NOT* clobbered; they are assumed to retain their value. -hpa |
![]() |
| Thread Tools | |
| Display Modes | |
In an effort to better serve ads to our visitors, cookies are used on objectmix.com. For more information, check out our Privacy Policy.