* Assembly question
@ 2002-04-25 8:32 Szekeres Istvan
2002-04-25 23:52 ` Mark Zealey
0 siblings, 1 reply; 5+ messages in thread
From: Szekeres Istvan @ 2002-04-25 8:32 UTC (permalink / raw)
To: linux-kernel
Hi,
Long time ago (older gcc) this code snippet used to compile. Now it doesn't.
Do you asm gurus have any idea what is wrong?
void p_memset_dword( void *d, int b, int l )
{
__asm__ ("rep\n\t"
"stosl\n\t"
:
: "D" (d), "a" (b), "c" (l)
: "memory","edi", "eax", "ecx"
);
}
The compiler says:
a.c: In function `p_memset_dword':
a.c:9: Invalid `asm' statement:
a.c:9: fixed or forbidden register 0 (ax) was spilled for class AREG.
Thanks,
Pista
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Assembly question
2002-04-25 8:32 Assembly question Szekeres Istvan
@ 2002-04-25 23:52 ` Mark Zealey
2002-04-26 11:37 ` Gabriel Paubert
0 siblings, 1 reply; 5+ messages in thread
From: Mark Zealey @ 2002-04-25 23:52 UTC (permalink / raw)
To: linux-kernel; +Cc: Szekeres Istvan
On Thu, Apr 25, 2002 at 10:32:25AM +0200, Szekeres Istvan wrote:
> void p_memset_dword( void *d, int b, int l )
> {
> __asm__ ("rep\n\t"
> "stosl\n\t"
> :
> : "D" (d), "a" (b), "c" (l)
> : "memory","edi", "eax", "ecx"
An input or output operand is implicitly clobbered, so it should be written as:
: "D" (d), "a" (b), "c" (l)
: "memory"
Or so.
--
Mark Zealey (aka JALH on irc.openprojects.net: #zealos and many more)
mark@zealos.org; mark@itsolve.co.uk
UL++++>$ G!>(GCM/GCS/GS/GM) dpu? s:-@ a17! C++++>$ P++++>+++++$ L+++>+++++$
!E---? W+++>$ !w--- r++ !t---?@ !X---? !R- !tv b+ G+++ e>+++++ !h++* r!-- y--
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Assembly question
2002-04-25 23:52 ` Mark Zealey
@ 2002-04-26 11:37 ` Gabriel Paubert
2002-04-26 12:34 ` Richard B. Johnson
0 siblings, 1 reply; 5+ messages in thread
From: Gabriel Paubert @ 2002-04-26 11:37 UTC (permalink / raw)
To: Mark Zealey; +Cc: linux-kernel
Mark Zealey wrote:
> On Thu, Apr 25, 2002 at 10:32:25AM +0200, Szekeres Istvan wrote:
>
>
>> void p_memset_dword( void *d, int b, int l ) { __asm__ ("rep\n\t"
"stosl\n\t"
>>
>> : : "D" (d), "a" (b), "c" (l) : "memory","edi", "eax", "ecx"
>>
>
> An input or output operand is implicitly clobbered, so it should be
^^^^^
I had expected gcc specialists to jump on that one: if you don't
explicitly tell gcc that an input is clobbered, it may reuse it later if
it needs the same value. So the clobbers are necessary...
Your statement about output operands is also incorrect, since clobbered
means that the register has an unknown value, which can not be used for
_anything_, while outputs are results from the statement and they'll
likely be used later (if none of the outputs is ever used and the asm
statement is not marked volatile, gcc will not even bother to emit it).
Regards,
Gabriel.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Assembly question
2002-04-26 11:37 ` Gabriel Paubert
@ 2002-04-26 12:34 ` Richard B. Johnson
2002-04-28 18:07 ` Zack Weinberg
0 siblings, 1 reply; 5+ messages in thread
From: Richard B. Johnson @ 2002-04-26 12:34 UTC (permalink / raw)
To: Gabriel Paubert; +Cc: Mark Zealey, linux-kernel
On Fri, 26 Apr 2002, Gabriel Paubert wrote:
> Mark Zealey wrote:
>
> > On Thu, Apr 25, 2002 at 10:32:25AM +0200, Szekeres Istvan wrote:
> >
> >
> >> void p_memset_dword( void *d, int b, int l ) { __asm__ ("rep\n\t"
> "stosl\n\t"
> >>
>
> >> : : "D" (d), "a" (b), "c" (l) : "memory","edi", "eax", "ecx"
> >>
> >
> > An input or output operand is implicitly clobbered, so it should be
> ^^^^^
> I had expected gcc specialists to jump on that one: if you don't
> explicitly tell gcc that an input is clobbered, it may reuse it later if
> it needs the same value. So the clobbers are necessary...
: : "D" (d), "a" (b), "c" (l) : "memory","edi", "eax", "ecx"
... is correct. Registers EDI, EAX, and ECX are altered and memory
is changed. Nothing having to do with the 'input' is altered in
any meaningful sense. You alter an 'input' by doing something like:
pushl %ebx
..... code
popl %eax ; Input value of ebx is destroyed
Passed parameters are (usually) passed on the stack. They are
local and disappear when the call returns, i.e.,
pushl string ; 4 - byte address
call puts ; call function
addl $4, esp ; Level stack
GCC may optimize in-line and not bother to push a value that is
readily accessible to the in-line function. That value is not
clobbered in any way. The in-line function doesn't have to
'return' since it's in-line. Therefore the return address isn't
on the stack either. When setting up 'clobbers', you have
observe the registers that are used and declare whether or
not memory is altered. That's all. For instance, we see EAX as
a clobbered register. GCC may decide that it is a scratch-register
so it doesn't bother to save/restore its value. On the other hand,
if you didn't tell GCC that you destroyed EAX, it's a bug and a
hard-to-find bug because most of the time, the code will work.
Cheers,
Dick Johnson
Penguin : Linux version 2.4.18 on an i686 machine (797.90 BogoMips).
Windows-2000/Professional isn't.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Assembly question
2002-04-26 12:34 ` Richard B. Johnson
@ 2002-04-28 18:07 ` Zack Weinberg
0 siblings, 0 replies; 5+ messages in thread
From: Zack Weinberg @ 2002-04-28 18:07 UTC (permalink / raw)
To: linux-kernel
Richard Johnson wrote:
> Gabriel Paubert wrote:
> > Mark Zealey wrote:
> > > Szekeres Istvan wrote:
> > >> void p_memset_dword( void *d, int b, int l ) {
> > >> __asm__ ("rep\n\t"
> > >> "stosl\n\t"
> > >> : : "D" (d), "a" (b), "c" (l)
> > >> : "memory","edi", "eax", "ecx");
> > >> }
> > >
> > > An input or output operand is implicitly clobbered, so it should be
> > ^^^^^
> > I had expected gcc specialists to jump on that one: if you don't
> > explicitly tell gcc that an input is clobbered, it may reuse it later if
> > it needs the same value. So the clobbers are necessary...
>
> : : "D" (d), "a" (b), "c" (l) : "memory","edi", "eax", "ecx"
> ... is correct. Registers EDI, EAX, and ECX are altered and memory
> is changed. Nothing having to do with the 'input' is altered in
> any meaningful sense.
As usual you are completely wrong. Clobbers can be used ONLY for
registers that do not already appear in either the input or output
list. In this case, it is the input registers that are modified. You
have to use notation that makes that explicit.
The correct way to write this asm statement with GCC 2.95 or later is
asm volatile
("rep; stosl"
: "+D" (d), "+c" (l) /* read and write edi, ecx */
: "a" (b)
: "memory");
With earlier versions you have to use a more verbose notation.
Some further notes:
rep stosl doesn't change %eax, so a plain input parameter can be used
for that argument.
GCC assumes that any asm with output parameters has no side effects.
The memory clobber doesn't count. Therefore, it will notice that d
and l are not used again and delete the whole asm statement, unless
you qualify it with 'volatile'.
There is no point in using __asm__ instead of asm, unless you are
writing code which has to compile with -pedantic on.
zw
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2002-04-28 18:07 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-04-25 8:32 Assembly question Szekeres Istvan
2002-04-25 23:52 ` Mark Zealey
2002-04-26 11:37 ` Gabriel Paubert
2002-04-26 12:34 ` Richard B. Johnson
2002-04-28 18:07 ` Zack Weinberg
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox