Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

understanding clobber list in GNU inline ASM

2,221 views
Skip to first unread message

ditiem

unread,
Aug 15, 2008, 3:49:02 PM8/15/08
to
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

DJ Delorie

unread,
Aug 15, 2008, 5:17:58 PM8/15/08
to

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.

ditiem

unread,
Aug 16, 2008, 4:19:58 AM8/16/08
to
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

Jike Song

unread,
Aug 17, 2008, 10:42:07 PM8/17/08
to
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.

H. Peter Anvin

unread,
Aug 19, 2008, 5:00:32 PM8/19/08
to
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

Jike Song

unread,
Aug 19, 2008, 10:57:29 PM8/19/08
to
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...

H. Peter Anvin

unread,
Aug 20, 2008, 11:11:42 PM8/20/08
to
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

ditiem

unread,
Aug 20, 2008, 8:57:44 PM8/20/08
to
> 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.

0 new messages