Discussion:
"asm" vs "asm volatile" vs "__asm__" vs "__asm__ __volatile__" etc in GCC
(too old to reply)
Brian
2005-12-04 01:33:26 UTC
Permalink
All,

I just spent 30 minutes trying to work out why the code I wrote in NASM
doesn't work after I convert it to inline assembler. When I went to
compare the byte code outputs of both I realised I couldn't find the
inline assembly code anywhere. I know GCC was seeing it because I had
made a couple of typos in the ASM syntax and GCC was complaining about
that.

I looked at my other inline assembly code and each of them used the
'volatile' keyword as well, so I added that and suddenly my asm code
appeared in GCC's output.

I thought 'volatile' meant "don't change the order of this statement in
relation to the others around it" or similar. Why did GCC not output
the code at all without the 'volatile' keyword as well?

Here is the code, just in case it matters:

asm volatile (
" mov $0x378, %%dx \n" // specify the data port
" out %%al, %%dx \n" // write the letter
" mov $0x37A, %%dx \n" // specify the control port
" mov $0x00D, %%al \n" // tell the hardware to send
the data
" out %%al, %%dx \n"
" mov $0x00C, %%al \n" // tell the hardware to stop
sending the data
" out %%al, %%dx \n"
: /* output */
"=a" (theAttr) // value of eax is changed
: /* input */
"a" (theGlyph) // eax needs to have
'theGlyph' stored in it.
: /* clobber */
"edx" // edx is used by 'out' and
so is clobbered
);

While we're on the discussion, how do the double-underscore variants
differ from the ones I've used? I tried using those earlier but
resorted back to the non-underscore versions (can't recall why, maybe
it was just aesthetics after I'd proved to myself that they worked
similarly).

Thanks,
Brian.
andreyw
2005-12-04 02:41:11 UTC
Permalink
I don't think your assembly is correct. You are only supposed to prefix
a register name with two percents *if* it's used in the input/output
lists. If you fix this I'm sure you won't need volatile. Since you are
doing port I/O, I would make this volatile anyhow, since you don't want
GCC to perform any optimizations around this code block.

As to __asm__/asm - Normal C doesn't know about asm (but
underscore_undersore_ stuff is reserved), hence you could potentially
have a variable called 'asm'. The behaviour is indentical. Use __asm__
if you intend to compile your code with anything other than GCC.

As always, reference the most excellent GCC-Inline-Assembly FAQ. Also
keep in mind that constraint modifiers tend to vary with target CPU
architectures (modulo phase of the moon).
Post by Brian
All,
I just spent 30 minutes trying to work out why the code I wrote in NASM
doesn't work after I convert it to inline assembler. When I went to
compare the byte code outputs of both I realised I couldn't find the
inline assembly code anywhere. I know GCC was seeing it because I had
made a couple of typos in the ASM syntax and GCC was complaining about
that.
I looked at my other inline assembly code and each of them used the
'volatile' keyword as well, so I added that and suddenly my asm code
appeared in GCC's output.
I thought 'volatile' meant "don't change the order of this statement in
relation to the others around it" or similar. Why did GCC not output
the code at all without the 'volatile' keyword as well?
asm volatile (
" mov $0x378, %%dx \n" // specify the data port
" out %%al, %%dx \n" // write the letter
" mov $0x37A, %%dx \n" // specify the control port
" mov $0x00D, %%al \n" // tell the hardware to send
the data
" out %%al, %%dx \n"
" mov $0x00C, %%al \n" // tell the hardware to stop
sending the data
" out %%al, %%dx \n"
: /* output */
"=a" (theAttr) // value of eax is changed
: /* input */
"a" (theGlyph) // eax needs to have
'theGlyph' stored in it.
: /* clobber */
"edx" // edx is used by 'out' and
so is clobbered
);
While we're on the discussion, how do the double-underscore variants
differ from the ones I've used? I tried using those earlier but
resorted back to the non-underscore versions (can't recall why, maybe
it was just aesthetics after I'd proved to myself that they worked
similarly).
Thanks,
Brian.
andreyw
2005-12-04 02:42:44 UTC
Permalink
I forgot to provide a link :-(. Here it is -
http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html
Scott Wood
2005-12-04 03:09:43 UTC
Permalink
Post by andreyw
I don't think your assembly is correct. You are only supposed to prefix
a register name with two percents *if* it's used in the input/output
lists.
Huh? You double the percent in order to get a single percent to the
assembler. It has nothing to do with whether the register is on the
input/output list, other than that if it's on the list you can refer
to it by number (and thus use a single percent).
Post by andreyw
If you fix this I'm sure you won't need volatile.
Using the wrong number of percent signs will generally cause a
compiler or assembler error, not missing code.

The most likely reason for the assembly code being missing is if the
output was not consumed.
Post by andreyw
Since you are doing port I/O, I would make this volatile anyhow,
since you don't want GCC to perform any optimizations around this
code block.
It should also have "memory" listed as a clobber; without it, some
reordering around the asm can still take place.
Post by andreyw
As to __asm__/asm - Normal C doesn't know about asm (but
underscore_undersore_ stuff is reserved), hence you could potentially
have a variable called 'asm'. The behaviour is indentical. Use __asm__
if you intend to compile your code with anything other than GCC.
If you intend to compile the code with non-GCC compilers, using
underscores isn't going to help with the GCC-specific syntax. Even
if the compiler in question supports GCC inline asm syntax but
requires __asm__ (do any such compilers exist?) you could always
#define asm __asm__ and avoid the ugly underscores.

-Scott
Maxim S. Shatskih
2005-12-04 12:01:06 UTC
Permalink
Post by andreyw
have a variable called 'asm'. The behaviour is indentical. Use __asm__
if you intend to compile your code with anything other than GCC.
No, __asm__ is GCCism. For Microsoft, it is:

__asm
{
asm code
}

Note: MS has dropped the inline asm support in x64 and IA64 compilers.
--
Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
***@storagecraft.com
http://www.storagecraft.com
Alexei A. Frounze
2005-12-04 08:08:07 UTC
Permalink
For a set of good examples on using x86 inline ASM with gcc consult:

- DJGPP standard C library (actually, not so standard pieces of it, there're
macros for far pointers and ports)
- Allegro game library (it's also for DJGPP) -- find the most recent version
of the library and see the source code -- there're lots of ASM optimizations

HTH,
Alex
Post by Brian
All,
I just spent 30 minutes trying to work out why the code I wrote in NASM
doesn't work after I convert it to inline assembler. When I went to
compare the byte code outputs of both I realised I couldn't find the
inline assembly code anywhere. I know GCC was seeing it because I had
made a couple of typos in the ASM syntax and GCC was complaining about
that.
I looked at my other inline assembly code and each of them used the
'volatile' keyword as well, so I added that and suddenly my asm code
appeared in GCC's output.
I thought 'volatile' meant "don't change the order of this statement in
relation to the others around it" or similar. Why did GCC not output
the code at all without the 'volatile' keyword as well?
asm volatile (
" mov $0x378, %%dx \n" // specify the data port
" out %%al, %%dx \n" // write the letter
" mov $0x37A, %%dx \n" // specify the control port
" mov $0x00D, %%al \n" // tell the hardware to send
the data
" out %%al, %%dx \n"
" mov $0x00C, %%al \n" // tell the hardware to stop
sending the data
" out %%al, %%dx \n"
: /* output */
"=a" (theAttr) // value of eax is changed
: /* input */
"a" (theGlyph) // eax needs to have
'theGlyph' stored in it.
: /* clobber */
"edx" // edx is used by 'out' and
so is clobbered
);
While we're on the discussion, how do the double-underscore variants
differ from the ones I've used? I tried using those earlier but
resorted back to the non-underscore versions (can't recall why, maybe
it was just aesthetics after I'd proved to myself that they worked
similarly).
Thanks,
Brian.
Loading...