More inline assembly caveats ('asm' tutorial)
strauman at slac.stanford.edu
Wed Feb 4 22:12:16 UTC 2009
Here's a new morsel:
The mvme167 BSP does something like that
void _BSP_output_char(char c)
char cr = '\r';
/* convert '\n' -> '\n' '\r' sequence */
if ( '\n' == c )
In 4.9 (gcc 4.3.2) this doesn't work anymore.
_167Bug_pollWrite contains inline assembly;
void _167Bug_pollWrite(const char *buf, int len)
asm volatile( <actual assembly code> :: "a"(buf), "a"(buf+len) );
Newer gccs are 'smart' enough to realize that
the value the 'cr' variable was initialized with
is never used and hence optimizes storing the '\r'
character into memory away (because it is NOT
smart enough to actually understand the inline
assembly code and realize that the value is needed
The naive approach here would be to proceed as
suggested by the gcc manual and add 'len' bytes
of memory starting at 'buf' to the list of
input operands. HOWEVER: this does NOT necessarily
do what you want; the actual semantics are
different for each architecture and may have
side-effects which are undocumented.
For an discussion and explanation consult this thread:
In the above case I could gcc 4.3.2 get to do
what is needed (i.e., storing the '\r' character
in memory) by either
1) declaring the 'cr' variable 'volatile'
volatile const char cr = '\r';
2) adding a general 'memory barrier' but this may be
more costly than 1) or having a proper way to
tell gcc that the inline asm reads or writes
a specific memory region (again: adding a memory
input/output operand may have OTHER SIDEEFFECTS
which are not documented in the gcc manual and
differ for each architecture).
const char cr = '\r';
3) In this particular example, our variable is actually
constant so we could make it a static variable and
hope it is actually initialized:
static const char cr = '\r';
4) Same rationale: use a static string
Hope this helps alerting people that inline assembly
has to be used with extreme care and is best avoided.
PS: This was filed as PR#1370
More information about the users