write to memory map I/O in a for loop

P

pointer noob

Hi,

I am trying to write a bit of code to iterate through memory addresses
and if the address is divisable by 2 then write one byte, if not write
a different byte. I am having trouble with the pointer to the address
incremented by for loop.

unsigned long i;

for(i=0xB8000; i<0xC0000; i++)
{
if (i % 2)
*(short *)i = 0x20;
else
*(short *)i = 0x07;
}

Does this look right? I found the *(short *) syntax online in another
bit of code that was used in a if statement, but I am not sure how this
statement works. My guess is it declares the data type at the address
being pointed to, but I cant find anything to confirm that. Or if
someone knows a better way to accomplish this, I would be very
grateful.

In case anyone is wondering, this chunk should blank a video screen.

Thanks for your time...
 
K

Keith Thompson

pointer noob said:
I am trying to write a bit of code to iterate through memory addresses
and if the address is divisable by 2 then write one byte, if not write
a different byte. I am having trouble with the pointer to the address
incremented by for loop.

unsigned long i;

for(i=0xB8000; i<0xC0000; i++)
{
if (i % 2)

Equivalent to "if (i % 2 != 0)", i.e., checks whether i is odd.
*(short *)i = 0x20;
else
*(short *)i = 0x07;
}

Does this look right? I found the *(short *) syntax online in another
bit of code that was used in a if statement, but I am not sure how this
statement works. My guess is it declares the data type at the address
being pointed to, but I cant find anything to confirm that. Or if
someone knows a better way to accomplish this, I would be very
grateful.

i is a variable of type unsigned long.

(short *)i converts the value of i to type short*, i.e., it converts
an integer to a pointer. The way in which this conversion is done
is system-specific.

Once you have this pointer, the unary "*" operator dereferences it.
So

*(short *)i = 0x20;

assigns the value 0x20 to whatever address corresponds to the integer
value of i.

Typically short is 16 bits, and bytes are 8 bits. If so, incrementing
an address is likely to advance the address by one byte; you're
writing a 16-bit value every 8 bits. It's unlikely that that's really
what you want to do. If nothing else, you'll have alignment problems
on many systems. Perhaps you want to use unsigned char* rather than
short*.
In case anyone is wondering, this chunk should blank a video screen.

It may do so on some specific system. Your code is *extremely*
system-specific. Many systems won't allow you to write directly to
video memory or to a specified address.
 
P

pointer noob

Thanks Keith,

So I changed the code as follows:

unsigned long i;

for(i=0xB8000; i<0xC0000; i++)
{
if (i % 2)
*(char *)i = 0x07;
else
*(char *)i = 0x20;
}
From your response, I found two errors, one was the boolean modulus
evaluating to true when odd, and then the size of the dereferenced
pointer value. Thanks again for your help...
 
K

Keith Thompson

pointer noob said:
Thanks Keith,

You're welcome. My fee is quite reasonable; just read
So I changed the code as follows:

unsigned long i;

for(i=0xB8000; i<0xC0000; i++)
{
if (i % 2)
*(char *)i = 0x07;
else
*(char *)i = 0x20;
}

evaluating to true when odd, and then the size of the dereferenced
pointer value. Thanks again for your help...

I would make the test more explicit: "if (i % 2 == 1)" rather than
"if (i % 2"). It's equivalent (in this case), but I prefer to make
conditional tests more explicit. (A lot of smart people disagree with
me on this point, so feel free to take it with a grain of salt.)

I have no way of knowing whether your code does what you want it to,
but if it works, that's great.
 
B

Ben Pfaff

pointer noob said:
unsigned long i;

for(i=0xB8000; i<0xC0000; i++)
{
if (i % 2)
*(char *)i = 0x07;
else
*(char *)i = 0x20;
}

I might write it like this:

char *base = (char *) 0xb8000;
unsigned offset = 0;
while (offset < 0x8000) {
base[offset++] = 0x20;
base[offset++] = 0x07;
}
 
R

Rod Pemberton

pointer noob said:
Thanks Keith,

So I changed the code as follows:

unsigned long i;

for(i=0xB8000; i<0xC0000; i++)
{
if (i % 2)
*(char *)i = 0x07;
else
*(char *)i = 0x20;
}

evaluating to true when odd, and then the size of the dereferenced
pointer value. Thanks again for your help...

The if-else and modulo are slow operations. Since the even and odd
addresses will always alternate, increment the counter by 2 storing 2 bytes
at a time. This works as long as your starting address is even.

for(i=0xB8000; i<0xC0000; i+=2)
{
*(unsigned char *)i = 0x07;
*(unsigned char *)(i+1) = 0x20;
}

for(i=0xB8000; i<0xC0000; i+=2)
{
*(unsigned short *)i = 0x2007; /* little endian */
}

Rod Pemberton
 
R

Richard G. Riley

Hi,

I am trying to write a bit of code to iterate through memory addresses
and if the address is divisable by 2 then write one byte, if not write
a different byte. I am having trouble with the pointer to the address
incremented by for loop.

unsigned long i;

for(i=0xB8000; i<0xC0000; i++)
{
if (i % 2)
*(short *)i = 0x20;
else
*(short *)i = 0x07;
}

Assuming char==byte and not being too anal and speeding it up considerably:

for(i=0xB8000; i<0xC0000; i+=2)
*(short *)i = 0x2007;


Its HW specific, but that doesnt matter since I'm assuming HW
specificness is a requirement because you are writing directly to
video memory. They were the days :) You may need "0x0720 depending on
endian issues.

You can make it twice as fast too : see if you can guess how.
 
K

Keith Thompson

Richard G. Riley said:
Assuming char==byte and not being too anal and speeding it up considerably:

char==byte is guaranteed by the language. Your assumption is that
short is 2 bytes.
for(i=0xB8000; i<0xC0000; i+=2)
*(short *)i = 0x2007;


Its HW specific, but that doesnt matter since I'm assuming HW
specificness is a requirement because you are writing directly to
video memory. They were the days :) You may need "0x0720 depending on
endian issues.

This may or may not work, depending on the underlying hardware. Since
the code is writing to specific hardwired addresses, whatever is at
those addresses might not even behave like ordinary memory. It's not
obvious that writing a 16-bit short will have the same effect as
writing two 8-bit bytes. (I suspect it does, but I wouldn't bet large
sums of money on it.)
 
R

Richard G. Riley

char==byte is guaranteed by the language. Your assumption is that
short is 2 bytes.


This may or may not work, depending on the underlying hardware.
Since

As I made clear.
the code is writing to specific hardwired addresses, whatever is at
those addresses might not even behave like ordinary memory. It's not
obvious that writing a 16-bit short will have the same effect as

He is clearing a memory buffer. It does.

writing two 8-bit bytes. (I suspect it does, but I wouldn't bet large
sums of money on it.)

I would.
 
M

Mark McIntyre

Hi,

I am trying to write a bit of code to iterate through memory addresses
and if the address is divisable by 2 then write one byte, if not write
a different byte.

I assume you're aware that on any modern OS this will abort with a
protection violation, since one is not allowed to directly write to
memory.
In case anyone is wondering, this chunk should blank a video screen.

Only on a decade old version of DOS. :)
Mark McIntyre
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,175
Messages
2,570,944
Members
47,491
Latest member
mohitk

Latest Threads

Top