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

How to write ANY value

37 views
Skip to first unread message

aleksa

unread,
Feb 21, 2011, 12:27:25 PM2/21/11
to
Some memory-mapped devices require a write to a specific
memory address in order to do something.
The data written is of no importance.

How can I instruct the compiler to write
whatever value it finds handy in that moment?

P.S.
That won't make the code much better, I'm just curious.

Ben Pfaff

unread,
Feb 21, 2011, 12:42:31 PM2/21/11
to
aleksa <alek...@gmail.com> writes:

> Some memory-mapped devices require a write to a specific
> memory address in order to do something.
> The data written is of no importance.
>
> How can I instruct the compiler to write
> whatever value it finds handy in that moment?

This may work:

unsigned char x;

*p = x;
--
Ben Pfaff
http://benpfaff.org

Jens Thoms Toerring

unread,
Feb 21, 2011, 1:23:10 PM2/21/11
to
aleksa <alek...@gmail.com> wrote:
> Some memory-mapped devices require a write to a specific
> memory address in order to do something.
> The data written is of no importance.

They typically are;-)

> How can I instruct the compiler to write
> whatever value it finds handy in that moment?

What means "handy at that moment"? That's a bit unspecific.
If you want to write just a single byte then, as Ben Pfaff
pointed out, using an unsigned char pointer (with the ad-
dress cast to that) would do. If you want to write more than
a single byte (but that would, of course, also work for a
single byte) you could use memcpy() to the target address,
cast to a void pointer. But there could be problems with
that: many devices want e.g. a single 16-bit or 32-bit wide
write or they won't do what you expect from such an access.
memcpy() is under no obligation to do it that way (even though
there's some chance that it copies in larger than 1-byte wide
chunks if possible). In device drivers you will often find
several functions for different wide accesses. If you need
e.g. to read or write 16-bit or 32-bit wide data instead of
an unsigned char (or uint8_t) pointer you'd use uint16_t or
uint32_t pointers. You have to carefully read the specifi-
cations for the hardware and decide which function to use
in each case - there's no fit-it-all function you could use
without further thought.
Regards, Jens
--
\ Jens Thoms Toerring ___ j...@toerring.de
\__________________________ http://toerring.de

Keith Thompson

unread,
Feb 21, 2011, 2:05:28 PM2/21/11
to
Ben Pfaff <b...@cs.stanford.edu> writes:
> aleksa <alek...@gmail.com> writes:
>
>> Some memory-mapped devices require a write to a specific
>> memory address in order to do something.
>> The data written is of no importance.
>>
>> How can I instruct the compiler to write
>> whatever value it finds handy in that moment?
>
> This may work:
>
> unsigned char x;
>
> *p = x;

Yes, but I'd be more comfortable with something like this:

#define ARBITRARY_DATA 42
*p = ARBITRARY_DATA;

For something other than a character type, reading an uninitialized
variable could allow the compiler to make certain assumptions that
could break your code. I think Ben's point is that the standard
makes certain extra guarantees about character types, but I wouldn't
want to depend on those guarantees without a good reason.

In either case, I'd say it's important to clearly document what you're
doing. (The name "ARBITRARY_DATA" is intended to do this.)

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

aleksa

unread,
Feb 21, 2011, 2:23:16 PM2/21/11
to
On Feb 21, 7:23 pm, j...@toerring.de (Jens Thoms Toerring) wrote:

> What means "handy at that moment"?

Writing whatever value is stored at that moment in whatever CPU
register.

Keith Thompson

unread,
Feb 21, 2011, 2:28:28 PM2/21/11
to

And how is that better than, for example, always writing 42?

aleksa

unread,
Feb 21, 2011, 2:36:20 PM2/21/11
to
On Feb 21, 8:05 pm, Keith Thompson <ks...@mib.org> wrote:
>     #define ARBITRARY_DATA 42
>     *p = ARBITRARY_DATA;

I was actually trying to avoid that approach,
because it requires the CPU to load a register with a
specific value, which isn't really necessary.

As I said to Jens:


"Writing whatever value is stored at that moment in whatever CPU

register",
without the need to initialize it first.

Maybe it is doable with in-line assembly, but I'm not sure how.
Maybe someone can adjust this (assuming DWORD access):
__asm *p = eax; // IA-32, write whatever was stored in EAX register.
__asm *p = R0; // ARM arch

Anders Wegge Keller

unread,
Feb 21, 2011, 2:37:10 PM2/21/11
to
Keith Thompson <ks...@mib.org> writes:

> aleksa <alek...@gmail.com> writes:
>> On Feb 21, 7:23 pm, j...@toerring.de (Jens Thoms Toerring) wrote:
>>> What means "handy at that moment"?
>>
>> Writing whatever value is stored at that moment in whatever CPU
>> register.
>
> And how is that better than, for example, always writing 42?

It shaves a whole instruction cycle off the write to the watchdog
register :)

I read the OP's question as "I know this won't make any difference,
but as an academic excersize, how could it be done?"

--
/Wegge

Leder efter redundant peering af dk.*,linux.debian.*

aleksa

unread,
Feb 21, 2011, 2:40:11 PM2/21/11
to
On Feb 21, 8:37 pm, Anders Wegge Keller <we...@wegge.dk> wrote:

>  I read the OP's question as "I know this won't make any difference,
> but as an academic excersize, how could it be done?"

Exactly :)

Sherm Pendley

unread,
Feb 21, 2011, 2:45:25 PM2/21/11
to
aleksa <alek...@gmail.com> writes:

> On Feb 21, 8:05 pm, Keith Thompson <ks...@mib.org> wrote:
>>     #define ARBITRARY_DATA 42
>>     *p = ARBITRARY_DATA;
>
> I was actually trying to avoid that approach,
> because it requires the CPU to load a register with a
> specific value, which isn't really necessary.

Not necessarily - all of the assembler languages I'm familiar with have
an instruction to store a literal value, and I assume any decent compiler
would emit such an instruction if given the above code.

sherm--

--
Sherm Pendley
<http://camelbones.sourceforge.net>
Cocoa Developer

Ben Pfaff

unread,
Feb 21, 2011, 2:52:09 PM2/21/11
to
Sherm Pendley <sherm....@gmail.com> writes:

> aleksa <alek...@gmail.com> writes:
>
>> On Feb 21, 8:05 pm, Keith Thompson <ks...@mib.org> wrote:
>>>     #define ARBITRARY_DATA 42
>>>     *p = ARBITRARY_DATA;
>>
>> I was actually trying to avoid that approach,
>> because it requires the CPU to load a register with a
>> specific value, which isn't really necessary.
>
> Not necessarily - all of the assembler languages I'm familiar with have
> an instruction to store a literal value, and I assume any decent compiler
> would emit such an instruction if given the above code.

Based on a few minutes looking around the Internet, I don't think
that ARM has a "store immediate" instruction.
--
"Give me a couple of years and a large research grant,
and I'll give you a receipt." --Richard Heathfield

aleksa

unread,
Feb 21, 2011, 3:00:15 PM2/21/11
to
On Feb 21, 8:45 pm, Sherm Pendley <sherm.pend...@gmail.com> wrote:

> aleksa <aleks...@gmail.com> writes:
> > On Feb 21, 8:05 pm, Keith Thompson <ks...@mib.org> wrote:
> >>     #define ARBITRARY_DATA 42
> >>     *p = ARBITRARY_DATA;
>
> > I was actually trying to avoid that approach,
> > because it requires the CPU to load a register with a
> > specific value, which isn't really necessary.
>
> Not necessarily - all of the assembler languages I'm familiar with have
> an instruction to store a literal value, and I assume any decent compiler
> would emit such an instruction if given the above code.

Yes, I've forgotten about that...
But that is usually a 1 byte longer instruction :)

aleksa

unread,
Feb 21, 2011, 3:01:27 PM2/21/11
to
On Feb 21, 8:45 pm, Sherm Pendley <sherm.pend...@gmail.com> wrote:
> aleksa <aleks...@gmail.com> writes:
> > On Feb 21, 8:05 pm, Keith Thompson <ks...@mib.org> wrote:
> >>     #define ARBITRARY_DATA 42
> >>     *p = ARBITRARY_DATA;
>
> > I was actually trying to avoid that approach,
> > because it requires the CPU to load a register with a
> > specific value, which isn't really necessary.
>
> Not necessarily - all of the assembler languages I'm familiar with have
> an instruction to store a literal value, and I assume any decent compiler
> would emit such an instruction if given the above code.

Yes, I've forgotten about that...


But that is usually a 1 byte longer instruction :)

And I'm not sure if ARM can do that, especially if its
base + offset = data

Eric Sosman

unread,
Feb 21, 2011, 3:27:03 PM2/21/11
to
On 2/21/2011 2:36 PM, aleksa wrote:
> On Feb 21, 8:05 pm, Keith Thompson<ks...@mib.org> wrote:
>> #define ARBITRARY_DATA 42
>> *p = ARBITRARY_DATA;
>
> I was actually trying to avoid that approach,
> because it requires the CPU to load a register with a
> specific value, which isn't really necessary.
>
> As I said to Jens:
> "Writing whatever value is stored at that moment in whatever CPU
> register",
> without the need to initialize it first.

There's no way to do this in C. There may be ways to do it in
a particular implementation of C, with a particular set of compiler
options, under a particular set of conditions that enable or prevent
particular optimizations, if you're a left-handed seventh son of a
seventh son programming in an abandoned churchyard by the light of
the second full Moon of an odd-numbered month.

(In short, if you're counting the individual instructions that
the machine executes to carry out the intent of your code, C is not
the way to express that intent. Wrong tool; use another.)

--
Eric Sosman
eso...@ieee-dot-org.invalid

Anders Wegge Keller

unread,
Feb 21, 2011, 3:36:38 PM2/21/11
to
Keith Thompson <ks...@mib.org> writes:

> Yes, but I'd be more comfortable with something like this:
>
> #define ARBITRARY_DATA 42
> *p = ARBITRARY_DATA;

It just occurred to me, that noone have mentioned the volatile
keyword yet. Especially this case, where the same value is written
repeatedly, is warranting a volatile declaration of p. Otherwise te
compile may end up optimizing any but the first write into oblibion.

aleksa

unread,
Feb 21, 2011, 3:43:13 PM2/21/11
to
On Feb 21, 9:36 pm, Anders Wegge Keller <we...@wegge.dk> wrote:

>  It just occurred to me, that noone have mentioned the volatile
> keyword yet.

Hardware registers are to be defined as volatile, yes.
(not that it changes the original question, though)

aleksa

unread,
Feb 21, 2011, 4:04:06 PM2/21/11
to
On Feb 21, 6:42 pm, Ben Pfaff <b...@cs.stanford.edu> wrote:
> This may work:
>
>     unsigned char x;
>
>     *p = x;

It doesn't as I would like.
My compiler stores 0 in reg, then reg to memory.
(as opposed to just storing a reg to memory)

Keith Thompson

unread,
Feb 21, 2011, 4:14:11 PM2/21/11
to

Does your compiler generate code to store 0, or does the register
just happen to contain 0?

aleksa

unread,
Feb 21, 2011, 4:19:54 PM2/21/11
to
On Feb 21, 10:14 pm, Keith Thompson <ks...@mib.org> wrote:

> Does your compiler generate code to store 0, or does the register
> just happen to contain 0?

The first one.

Sjouke Burry

unread,
Feb 21, 2011, 4:38:15 PM2/21/11
to
Keith Thompson wrote:
> aleksa <alek...@gmail.com> writes:
>> On Feb 21, 6:42 pm, Ben Pfaff <b...@cs.stanford.edu> wrote:
>>> This may work:
>>>
>>> unsigned char x;
>>>
>>> *p = x;
>> It doesn't as I would like.
>> My compiler stores 0 in reg, then reg to memory.
>> (as opposed to just storing a reg to memory)
>
> Does your compiler generate code to store 0, or does the register
> just happen to contain 0?
>
It might be useful to give x some value.......

Ben Pfaff

unread,
Feb 21, 2011, 4:50:20 PM2/21/11
to
Sjouke Burry <burrynu...@ppllaanneett.nnll> writes:

The whole point was to not give x a value; please read back to
the beginning of the thread.
--
char a[]="\n .CJacehknorstu";int putchar(int);int main(void){unsigned long b[]
={0x67dffdff,0x9aa9aa6a,0xa77ffda9,0x7da6aa6a,0xa67f6aaa,0xaa9aa9f6,0x11f6},*p
=b,i=24;for(;p+=!*p;*p/=4)switch(0[p]&3)case 0:{return 0;for(p--;i--;i--)case+
2:{i++;if(i)break;else default:continue;if(0)case 1:putchar(a[i&15]);break;}}}

Sjouke Burry

unread,
Feb 21, 2011, 4:59:51 PM2/21/11
to
Ben Pfaff wrote:
> Sjouke Burry <burrynu...@ppllaanneett.nnll> writes:
>
>> Keith Thompson wrote:
>>> aleksa <alek...@gmail.com> writes:
>>>> On Feb 21, 6:42 pm, Ben Pfaff <b...@cs.stanford.edu> wrote:
>>>>> This may work:
>>>>>
>>>>> unsigned char x;
>>>>>
>>>>> *p = x;
>>>> It doesn't as I would like.
>>>> My compiler stores 0 in reg, then reg to memory.
>>>> (as opposed to just storing a reg to memory)
>>> Does your compiler generate code to store 0, or does the register
>>> just happen to contain 0?
>>>
>> It might be useful to give x some value.......
>
> The whole point was to not give x a value; please read back to
> the beginning of the thread.
So *p gets random data from who knows what location? Right,
I did not know about that valuable mechanism......

Ian Collins

unread,
Feb 21, 2011, 5:05:50 PM2/21/11
to

Did you read the OP?

"Some memory-mapped devices require a write to a specific
memory address in order to do something.
The data written is of no importance."

Hardware watchdogs are a common example of this.

--
Ian Collins

Ben Pfaff

unread,
Feb 21, 2011, 5:12:36 PM2/21/11
to
Ian Collins <ian-...@hotmail.com> writes:

> Did you read the OP?
>
> "Some memory-mapped devices require a write to a specific
> memory address in order to do something.
> The data written is of no importance."
>
> Hardware watchdogs are a common example of this.

Some 16-color EGA/VGA display modes were another case. Here's
the comment that I put into the Linux 16-color framebuffer driver
many years ago when I wrote it:

/* The VGA's weird architecture often requires that we read a byte and
write a byte to the same location. It doesn't matter *what* byte
we write, however. This is because all the action goes on behind
the scenes in the VGA's 32-bit latch register, and reading and writing
video memory just invokes latch behavior.

To avoid race conditions (is this necessary?), reading and writing
the memory byte should be done with a single instruction. One
suitable instruction is the x86 bitwise OR. The following
read-modify-write routine should optimize to one such bitwise
OR. */

(It seems that someone modified the code and didn't update the
comment, though, since the code no longer uses a single
instruction to do it. I guess it wasn't necessary.)

James Waldby

unread,
Feb 21, 2011, 5:35:44 PM2/21/11
to
On Mon, 21 Feb 2011 22:38:15 +0100, Sjouke Burry wrote:
> Keith Thompson wrote:
>> aleksa <aleksazr@gm..> writes:

>>> On Feb 21, 6:42 pm, Ben Pfaff wrote:
>>>> This may work:
>>>> unsigned char x;
>>>>
>>>> *p = x;
>>> It doesn't as I would like.
>>> My compiler stores 0 in reg, then reg to memory. (as
>>> opposed to just storing a reg to memory)
>>
>> Does your compiler generate code to store 0, or does
>> the register just happen to contain 0?
>>
> It might be useful to give x some value.......

The OP doesn't care what value is written, and just
wants a write to occur to a specific address. This is
a common paradigm in embedded systems, where you may
need to strobe an address via a read or write, and the
data involved is don't-care.

I have a 525-line C program that runs on an AT90S2313
(2K program memory, 128 byte SRAM) clocked at 500KHz
and if making changes occasionally have to look at the
assembly listing to figure out where I can save a few
cycles -- so I can understand the OP's concern about
unnecessarily loading a register. It's a bit more
difficult to understand the expectation of doing so
in a portable way.

--
jiw

William Ahern

unread,
Feb 21, 2011, 5:40:23 PM2/21/11
to
Ben Pfaff <b...@cs.stanford.edu> wrote:
<snip>

> To avoid race conditions (is this necessary?), reading and writing
> the memory byte should be done with a single instruction. One
> suitable instruction is the x86 bitwise OR. The following
> read-modify-write routine should optimize to one such bitwise
> OR. */
>
> (It seems that someone modified the code and didn't update the
> comment, though, since the code no longer uses a single
> instruction to do it. I guess it wasn't necessary.)

That's a very politic inference ;)

Edward A. Falk

unread,
Feb 21, 2011, 9:06:04 PM2/21/11
to
In article <0375a3a2-8f25-4d3a...@m7g2000vbq.googlegroups.com>,

My guess is that the compiler is generating code to initialize x.

I'd just leave it alone; we're talking like a billionth of a second
here.

By the way, more importantly:

volatile unsigned char *p;

--
-Ed Falk, fa...@despams.r.us.com
http://thespamdiaries.blogspot.com/

Gordon Burditt

unread,
Feb 22, 2011, 12:25:20 AM2/22/11
to
> Some memory-mapped devices require a write to a specific
> memory address in order to do something.
> The data written is of no importance.
>
> How can I instruct the compiler to write
> whatever value it finds handy in that moment?

Two suggestions:

1. Use the value of the last assignment statement you used, which may
still be lying around in a register.
E.g. change:
++count;
*io_port_pointer = 0;
to
*io_port_pointer = (++count);

Some things to watch out for, though:
1. Make sure it doesn't have to sign-extend (or even 0-extend)
the value. This might slow things down instead of
speeding something up.
2. Watch out for order-of-evaluation problems, such as
the previous expression also doing something with the same port.
3. Watch out for nasty type clashes, such as io_port_pointer being
a pointer to an 8-bit quantity and count being a pointer or
float.

2. Use 0. I have noticed that some embedded compilers (specifically,
gcc-avr for Atmel 8-bit microcontrollers) tend to keep the value 0
around by loading a register with it and keeping it there. It's
handy for such things as 0-extends, var16bit += var8bit, and
var32bit += var16bit. Even if the compiler has to load the value,
an instruction like "clear r1", "subtract r1, r1" or "xor r1,r1"
may be shorter and faster than an instruction like "load immediate r1, 0".

3. Ask the user (if there is one) to press any key (if there is one),
read its value, and use that. Just kidding.

Keith Thompson

unread,
Feb 22, 2011, 12:33:25 AM2/22/11
to
aleksa <alek...@gmail.com> writes:
> Some memory-mapped devices require a write to a specific
> memory address in order to do something.
> The data written is of no importance.
>
> How can I instruct the compiler to write
> whatever value it finds handy in that moment?
>
> P.S.
> That won't make the code much better, I'm just curious.

This might do what you want:

volatile register int junk;
volatile int *p = /* ... */;
*p = junk;

But there are no guarantees. You're trying to generate specific machine
code. A compiler's job is to generate machine code that has a specified
effect.

aleksa

unread,
Feb 22, 2011, 4:00:24 AM2/22/11
to
On Feb 21, 11:35 pm, James Waldby <n...@valid.invalid> wrote:

> It's a bit more difficult to understand the
> expectation of doing so in a portable way.

I didn't know if this is doable in portable C,
so I've asked here to be sure.

Since it looks like it is not,
I could post it somewhere else.

aleksa

unread,
Feb 22, 2011, 4:20:11 AM2/22/11
to
On Feb 22, 10:00 am, aleksa <aleks...@gmail.com> wrote:

> Since it looks like it is not,
> I could post it somewhere else.

I've wrote this before seeing that
there is a next page in google.

Gordon Burditt's "last assignment statement"
and Keith Thompson's "register" are good ideas.

Thanks, everyone.

aleksa

unread,
Feb 22, 2011, 6:42:34 AM2/22/11
to
On Feb 21, 6:27 pm, aleksa <aleks...@gmail.com> wrote:
> Some memory-mapped devices require a write to a specific
> memory address in order to do something.
> The data written is of no importance.
>
> How can I instruct the compiler to write
> whatever value it finds handy in that moment?
>
> P.S.
> That won't make the code much better, I'm just curious.

Andreas B. has an excellent idea - storing the pointer to itself!
http://embdev.net/topic/209508

*p = p;

or

BYTE *adr = ...; // or WORD / DWORD
*adr = adr;

Tested it on ARM and am quite sure it works on IA32:
mov [eax],al
mov [eax],ax
mov [eax],eax

aleksa

unread,
Feb 22, 2011, 6:51:52 AM2/22/11
to
On Feb 22, 12:42 pm, aleksa <aleks...@gmail.com> wrote:

> mov [eax],al
> mov [eax],ax
> mov [eax],eax

I'm more interested in ARM and
didn't think much about IA32.

IA32 could just store immediate to
direct address - one instruction only.

Tim Rentsch

unread,
Feb 23, 2011, 4:29:23 AM2/23/11
to
Ben Pfaff <b...@cs.stanford.edu> writes:

> aleksa <alek...@gmail.com> writes:
>
>> Some memory-mapped devices require a write to a specific
>> memory address in order to do something.
>> The data written is of no importance.
>>
>> How can I instruct the compiler to write
>> whatever value it finds handy in that moment?
>

> This may work:
>
> unsigned char x;
>
> *p = x;

Be warned! Even using 'unsigned char', under C1X this will be
undefined behavior. One way to fix that:

unsigned char x[1];

*p = *x;

BartC

unread,
Feb 23, 2011, 5:18:35 AM2/23/11
to

"aleksa" <alek...@gmail.com> wrote in message
news:81128877-408d-4e35...@d16g2000yqd.googlegroups.com...


> Some memory-mapped devices require a write to a specific
> memory address in order to do something.
> The data written is of no importance.
>
> How can I instruct the compiler to write
> whatever value it finds handy in that moment?

Surely for anything like this, you'd just use some inline assembly (perhaps
wrapped in a macro).

I wouldn't trust the compiler; it might do it once, then the next time won't
bother because it thinks that location already contains the same value!

--
Bartc

Anders Wegge Keller

unread,
Feb 23, 2011, 5:34:09 AM2/23/11
to
"BartC" <b...@freeuk.com> writes:

> I wouldn't trust the compiler; it might do it once, then the next
> time won't bother because it thinks that location already contains
> the same value!

That's why we have the volatile keyword.

BartC

unread,
Feb 23, 2011, 6:28:20 AM2/23/11
to

"Anders Wegge Keller" <we...@wegge.dk> wrote in message
news:87zkpnv...@huddi.jernurt.dk...


> "BartC" <b...@freeuk.com> writes:
>
>> I wouldn't trust the compiler; it might do it once, then the next
>> time won't bother because it thinks that location already contains
>> the same value!
>
> That's why we have the volatile keyword.

OK, but I'd still be wary of pretending i/o locations are really variables.

--
Bartc

Anders Wegge Keller

unread,
Feb 23, 2011, 6:44:48 AM2/23/11
to
"BartC" <b...@freeuk.com> writes:

Why?

A volatile declaration may be used to describe an object
corresponding to a memory-mapped input/output port or an object
accessed by an asynchronously interrupting function. Actions on
objects so declared shall not be ‘‘optimized out’’ by an
implementation or reordered except as permitted by the rules for
evaluating expressions.

Ben Bacarisse

unread,
Feb 23, 2011, 7:01:46 AM2/23/11
to
Tim Rentsch <t...@alumni.caltech.edu> writes:

> Ben Pfaff <b...@cs.stanford.edu> writes:
>
>> aleksa <alek...@gmail.com> writes:
>>
>>> Some memory-mapped devices require a write to a specific
>>> memory address in order to do something.
>>> The data written is of no importance.
>>>
>>> How can I instruct the compiler to write
>>> whatever value it finds handy in that moment?
>>
>> This may work:
>>
>> unsigned char x;
>>
>> *p = x;
>
> Be warned! Even using 'unsigned char', under C1X this will be
> undefined behavior.

Can you point to the change please? I had a look in what seemed like
the obvious places but did not find any smoking gun.

> One way to fix that:
>
> unsigned char x[1];
>
> *p = *x;

--
Ben.

Eric Sosman

unread,
Feb 23, 2011, 7:46:51 AM2/23/11
to

One problem is that "What constitutes an access to an object that
has volatile-qualified type is implementation-defined" (6.7.3p6). It
is often the case that a magical memory address performs its magic
only if accessed by the right kind of instruction: For example, an
"I/O register" at location 0xFF001010 might respond to a four-byte
load or store at that address but not even notice a one-byte access
to location 0xFF001012. Since there's no way to get C-the-language
to generate any particular hardware instruction, there's no way to be
sure C-the-language will use the one you desire.

(This is not a theoretical matter, by the way. I once asked a lead
kernel engineer for a large computer vendor why none of their device
drivers were written in C. Her answer amounted to essentially this
issue: The special locations in the hardware worked only when accessed
as a unit, not when accessed byte-by-byte, and there was no reliable way
to ensure that C would use the former -- *especially* if somebody chose
to compile with a "tolerate misaligned pointers" switch enabled...)

On a given implementation there may be ways to ensure that C uses
the desired instructions -- it could be as simple as reading the
implementation's documents. But you can't just shout `volatile' and
expect that all problems are solved, nor should you assume that the
solution for one machine will behave as desired on another.

--
Eric Sosman
eso...@ieee-dot-org.invalid

Anders Wegge Keller

unread,
Feb 23, 2011, 8:03:53 AM2/23/11
to
Eric Sosman <eso...@ieee-dot-org.invalid> writes:

> One problem is that "What constitutes an access to an object
> that has volatile-qualified type is implementation-defined"
> (6.7.3p6).

Yes, and I don't see that as a problem. After all, in the case where
any particular register is mapped into the address space, the
situation is already very specific.

...

> (This is not a theoretical matter, by the way.

I know. BTDTGTT, and all that.

> On a given implementation there may be ways to ensure that C
> uses the desired instructions -- it could be as simple as reading
> the implementation's documents. But you can't just shout `volatile'
> and expect that all problems are solved, nor should you assume that
> the solution for one machine will behave as desired on another.

Will you please decide if you want to discuss a specific
implementatio, or if you want to talk about a general case?

In the general case, adress 0x0842 has no universal meaning beyond
beaing an address. Thus, we never get to the point of having to worry
about different compilers ways with memory access.

In the specific case, on the other hand, where we acutally have a
well-defined meaning for that adress, I see no problem in acessing
it. I take it as a given that anyone doing low-level programming that
involves any amount of bit-baning will be competent enough to do so.

Tim Rentsch

unread,
Feb 23, 2011, 11:07:21 AM2/23/11
to
Ben Bacarisse <ben.u...@bsb.me.uk> writes:

Sorry, I should have mentioned this - last sentence of 6.3.2.1p2:

If the lvalue designates an object of automatic storage
duration that could have been declared with the register
storage class (never had its address taken), and that object
is uninitialized (not declared with an initializer and no
assignment to it has been performed prior to use), the
behavior is undefined.

Keith Thompson

unread,
Feb 23, 2011, 3:21:09 PM2/23/11
to
Anders Wegge Keller <we...@wegge.dk> writes:
[...]

> In the general case, adress 0x0842 has no universal meaning beyond
> beaing an address. Thus, we never get to the point of having to worry
> about different compilers ways with memory access.
[...]

In the general case, 0x0842 is not an address at all; it's of
type int. It can be *converted* to some pointer type, and such
a conversion is "intended to be consistent with the addressing
structure of the execution environment".

We often refer to things like " address 0x0842", but that's either a
convenient verbal shorthand for the above conversion, or something
outside the scope of the C language. (Address 0x0842 might well
be a meaningful concept in the context of a particular CPU.)

Anders Wegge Keller

unread,
Feb 23, 2011, 4:00:09 PM2/23/11
to
Keith Thompson <ks...@mib.org> writes:

> Anders Wegge Keller <we...@wegge.dk> writes:
> [...]
>> In the general case, adress 0x0842 has no universal meaning beyond
>> beaing an address. Thus, we never get to the point of having to worry
>> about different compilers ways with memory access.
> [...]
>
> In the general case, 0x0842 is not an address at all; it's of
> type int. It can be *converted* to some pointer type, and such
> a conversion is "intended to be consistent with the addressing
> structure of the execution environment".

Sorry for not being nit-picky enough do write (unsigned char
*0x0842). Quoting one of my colleagues, when we were at a Coccinelle
workshop "We're not C-linguists. We just use the language".

> We often refer to things like " address 0x0842", but that's either a
> convenient verbal shorthand for the above conversion, or something
> outside the scope of the C language. (Address 0x0842 might well
> be a meaningful concept in the context of a particular CPU.)

A lot of the things we do with C *is* outside the language proper. At
least, that's the case for me, and I expect that more and more of the
remaining C development is targeted at either freestanding
implementations in toasters etc. or low-level bit banging.

That will give some imprecise language that isn't proper in this
group, but please bear with me. I'm doubly challenged by also not
being a native english speaker.

Eric Sosman

unread,
Feb 23, 2011, 8:54:10 PM2/23/11
to
On 2/23/2011 4:00 PM, Anders Wegge Keller wrote:
> [...]

> A lot of the things we do with C *is* outside the language proper.

Yes, and the Rationale recognizes this explicitly. So does the
Standard itself, albeit only in non-normative material.

There is nothing -- *nothing* -- wrong with crossing the line
between fully portable C and system-specific C. In my opinion, it
is both common and laudable to cross that line at need. But in my
opinion it is also important to know where the line is, to know what
parts of the code will require effort to port and what parts will
"port themselves," and to take appropriate precautionary measures.
Like, for example, wrapping those `volatile' pointer-from-integer
constructs inside easily-segregated functions instead of just letting
them float free throughout the code. You questioned BartC's advice
to "be wary" of raw access to memory-mapped registers; I think his
wariness is good engineering practice.

> At
> least, that's the case for me, and I expect that more and more of the
> remaining C development is targeted at either freestanding
> implementations in toasters etc. or low-level bit banging.

I betcha, I betcha, I betchamillionbucks that next year's toaster
will use a different CPU. Quite likely (but not certainly) a CPU in
the same family as this year's, but enhanced/cost-reduced/spiffed-up
in some way or other. And, lo! the code will have to be ported.

We have arrived at a situation where "soft"ware is something of a
misnomer. It used to be "soft" because it was malleable, it could be
changed cheaply without modifying the expensive and hard-to-change
hardware that it ran on. Well, nowadays the "hard"ware changes have
become faster than they were, while "soft"ware changes have grown more
and more difficult. An investment in "soft"ware can only be justified
if it can be amortized over several generations of "hard"ware -- or, in
short, your code *will* be ported. If you do not prepare for that
inevitability, you make yourself a net resource drain and not a net
contributor.

As for bit-banging -- well, I liked your earlier message about
"bit-baning" better! Bits have been the bane of most of us, and I
imagine they'll continue to be so. :-)

(A European colleague once gave me his business card, which
described him as a "System-Berater," a German title we might render in
English as "System Advisor" or "System Consultant." But the English
verb "berate" means to scold or chastise, and I immediately pictured
the fellow wagging an admonitory forefinger at a recalcitrant computer
and saying "Bad system! Baaadddd system! No dessert for you!!!")

> That will give some imprecise language that isn't proper in this
> group, but please bear with me. I'm doubly challenged by also not
> being a native english speaker.

Anders, your English is one helluvalot better than my Norwegian!
There's a saying: If you speak many languages you're "multilingual,"
if you speak two languages you're "bilingual," and if you speak one
language you're "American."

--
Eric Sosman
eso...@ieee-dot-org.invalid

0 new messages