Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Help with pointers and absolute memory addresses

Reply
Thread Tools

Help with pointers and absolute memory addresses

 
 
Ian Collins
Guest
Posts: n/a
 
      04-27-2008
Yep wrote:
> Hi Guys,
>
> I have some confusion with pointers and implicitly specifying a size of
> memory to write.
>
> I will try to explain what I am trying to do a bit better.
>
> char *myaddress=(char *) 0xB8000;
>
> now, I can say something like:
>
> *myaddress=3;
>
> And the 8 bit value of '3' will be written at absolute address 0xB8000
>
> What if I want to explicitly write a 16 or 32 bit value to that address?


Just follow the same pattern,

T *myaddress = (T*)0xB8000;

*myaddress = someT;

--
Ian Collins.
 
Reply With Quote
 
 
 
 
Walter Roberson
Guest
Posts: n/a
 
      04-27-2008
In article <4814093c$0$17511$(E-Mail Removed)> ,
Yep <yep@yep> wrote:

>I have some confusion with pointers and implicitly specifying a size of
>memory to write.


>char *myaddress=(char *) 0xB8000;


>(unsigned short *) *myaddress=somevalue;


>Compiles but generates compiler warnings about lvalue of cast not being
>standard C.


Unfortunately for your purposes, standard C leaves it up to the
implementation to define what (if any) meaning there is to
converting an integer into a pointer, and what (if any) meaning
there is to accessing the resulting location.


That said: you would be better off trying:

*(unsigned short *)myaddress=somevalue;
--
"To burn always with this hard, gem-like flame, to maintain this
ecstasy, is success in life." -- Walter Pater
 
Reply With Quote
 
 
 
 
Yep
Guest
Posts: n/a
 
      04-27-2008
Hi Guys,

I have some confusion with pointers and implicitly specifying a size of
memory to write.

I will try to explain what I am trying to do a bit better.

char *myaddress=(char *) 0xB8000;

now, I can say something like:

*myaddress=3;

And the 8 bit value of '3' will be written at absolute address 0xB8000

What if I want to explicitly write a 16 or 32 bit value to that address?
Obviously I need to use casts to do this but my memory is terrible and
the compiler is unhappy with what I try.

Say for example:

unsigned short somevalue=0xffff; //watcom C unsigned short = 16 bit Uint

Now I want the content of 'somevalue' to be written at absolute address
'myaddress'

Whats the correct way to do this?

(unsigned short *) *myaddress=somevalue;

Compiles but generates compiler warnings about lvalue of cast not being
standard C.I have actually looked at the assembly code output this code
produces and it it not writing the correct size to that address.

Any suggestions/relevant reading tips would be appreciated, if the
advice is going to be about documentation on pointers, i need reading
that deals with this very subject.

Thanks in advance.
Alex.
 
Reply With Quote
 
Ian Collins
Guest
Posts: n/a
 
      04-27-2008
Yep wrote:
> Walter Roberson wrote:
>>
>> That said: you would be better off trying:
>>
>> *(unsigned short *)myaddress=somevalue;

>
> That works! Why is the extra * needed in front of the cast?


Maybe writing the expression as

*((unsigned short *)myaddress) = somevalue;

makes it clearer?

--
Ian Collins.
 
Reply With Quote
 
Yep
Guest
Posts: n/a
 
      04-27-2008
Richard Heathfield wrote:
> Yep said:
>
>> Hi Guys,
>>
>> I have some confusion with pointers and implicitly specifying a size of
>> memory to write.
>>
>> I will try to explain what I am trying to do a bit better.
>>
>> char *myaddress=(char *) 0xB8000;

>
> Is this an attempt to scribble on video RAM on an x86? If so, be warned
> that you'll need to be in real mode for it to work (more about that in
> comp.os.msdos.programmer). Also, I would recommend unsigned char * for
> this!


I used this as an example I am writing under 32 Bit Pmode in DOS, so
B8000 is correct (sorry for the off topicness), but the code will be
used to control peripherals with their MMAP'd space on the PCI bus.

>> now, I can say something like:
>>
>> *myaddress=3;
>>
>> And the 8 bit value of '3' will be written at absolute address 0xB8000

>
> Close. 3 rather than '3'. Assuming for the moment that we're using 8-bit
> char, 16-bit int, and ASCII: 3 is the bit-pattern 0000000000000011 (so the
> 8-bit equivalent would be 00000011), whereas '3' is the bit pattern
> 00110011. As you can see, these are not quite the same!
>


My bad. I shouldnt have put '' but yes, the value of 3 in binary, not
ascii. But to be technically correct writing a word value of 0x7f50 will
put a capital 'P' in white text on grey background on the screen, a
dword value 0x7f507f50 will put 2 of them as the ordering is
attrib,character.

>
> Final warning: this is *so* not a good idea. BAD BAD BAD IDEA, okay? Bad.
> If you insist on doing this, you will NOT get a biscuit.
>
> Nevertheless, if you must do it, that's one way to do it.


There is a reason for it. I need to be able to write explicit 8, 16, 32
bit values to any address within the 32 bit address space. This is
allowed on the platform I am writing (32 Bit Pmode under DOS).
 
Reply With Quote
 
Yep
Guest
Posts: n/a
 
      04-27-2008
Walter Roberson wrote:
>
> That said: you would be better off trying:
>
> *(unsigned short *)myaddress=somevalue;


That works! Why is the extra * needed in front of the cast?
 
Reply With Quote
 
Yep
Guest
Posts: n/a
 
      04-27-2008
Ian Collins wrote:
> Yep wrote:
>> Walter Roberson wrote:
>>> That said: you would be better off trying:
>>>
>>> *(unsigned short *)myaddress=somevalue;

>> That works! Why is the extra * needed in front of the cast?

>
> Maybe writing the expression as
>
> *((unsigned short *)myaddress) = somevalue;
>
> makes it clearer?
>


It does.

So its a pointer to the unsigned short, pointed to by myaddress.

I did a test case:

*((unsigned long *)myaddress) = somevalue; //32 bit
*((unsigned short *)myaddress) = somevalue; //16 bit
*((unsigned char *)myaddress) = somevalue; //8bit

And observed the assembly code generated by the compiler, the behavior
is correct.

Thank you!!!!!




 
Reply With Quote
 
santosh
Guest
Posts: n/a
 
      04-27-2008
Yep wrote:

> Ian Collins wrote:
>> Yep wrote:
>>> Walter Roberson wrote:
>>>> That said: you would be better off trying:
>>>>
>>>> *(unsigned short *)myaddress=somevalue;
>>> That works! Why is the extra * needed in front of the cast?

>>
>> Maybe writing the expression as
>>
>> *((unsigned short *)myaddress) = somevalue;
>>
>> makes it clearer?
>>

> It does.
>
> So its a pointer to the unsigned short, pointed to by myaddress.


I'm not clear about what you are saying above but that line actually
takes the value of myaddress (which is the address it holds) which of
type char * and explicitly converts it to a value of type unsigned
short *, then deferencing this value to write somevalue.

> I did a test case:
>
> *((unsigned long *)myaddress) = somevalue; //32 bit
> *((unsigned short *)myaddress) = somevalue; //16 bit
> *((unsigned char *)myaddress) = somevalue; //8bit


These are the least sizes that the C standard requires but they *could*
be bigger on some platforms. At least on the x86_64 under some OSes
long is actually 64 bits, so you might want to use casts to uint32_t *,
uint16_t *, and uint8_t * instead of unsigned long *, unsigned short *,
and unsigned char *. The former are guaranteed to be exactly those
sizes, without padding bits and in twos-complement format.

> And observed the assembly code generated by the compiler, the behavior
> is correct.
>
> Thank you!!!!!


 
Reply With Quote
 
cr88192
Guest
Posts: n/a
 
      04-27-2008

"Yep" <yep@yep> wrote in message
news:48141ac4$0$1025$(E-Mail Removed) ...
> Richard Heathfield wrote:
>> Yep said:
>>
>>> Hi Guys,
>>>
>>> I have some confusion with pointers and implicitly specifying a size of
>>> memory to write.
>>>
>>> I will try to explain what I am trying to do a bit better.
>>>
>>> char *myaddress=(char *) 0xB8000;

>>
>> Is this an attempt to scribble on video RAM on an x86? If so, be warned
>> that you'll need to be in real mode for it to work (more about that in
>> comp.os.msdos.programmer). Also, I would recommend unsigned char * for
>> this!

>
> I used this as an example I am writing under 32 Bit Pmode in DOS, so
> B8000 is correct (sorry for the off topicness), but the code will be used
> to control peripherals with their MMAP'd space on the PCI bus.
>


yes, I was about to comment that one should be sure of this one.
there is always the risk of some or another newb trying to compile something
like this in windows or linux and wondering why it doesn't work...

now, this construct is funky in that it will neither work in a full 32-bit
OS, nor in real-mode, so (raw or DPMI) pmode is needed (taking as an
assumption that there are no compilers targeting big-real mode...).


>>> now, I can say something like:
>>>
>>> *myaddress=3;
>>>
>>> And the 8 bit value of '3' will be written at absolute address 0xB8000

>>
>> Close. 3 rather than '3'. Assuming for the moment that we're using 8-bit
>> char, 16-bit int, and ASCII: 3 is the bit-pattern 0000000000000011 (so
>> the 8-bit equivalent would be 00000011), whereas '3' is the bit pattern
>> 00110011. As you can see, these are not quite the same!
>>

>
> My bad. I shouldnt have put '' but yes, the value of 3 in binary, not
> ascii. But to be technically correct writing a word value of 0x7f50 will
> put a capital 'P' in white text on grey background on the screen, a dword
> value 0x7f507f50 will put 2 of them as the ordering is attrib,character.
>


now what is more fun is moving the cursor, and implementing the code for
pulling off the usual scrolling textual display.

actually, interesting and possible is to implement an IRC style interface,
where the commandline is always pinned to the bottom of the screen and text
starts at the bottom and moves up...

of course, the more traditional interface also works fairly well (and is a
little more flexible, and mixes better with our good old friend ANSI control
codes...). actually, at the time I had found a copy of the VT100 manual and
implemented nearly every applicable command...

later on, this project (a hobby OS), ended up using ModeX and VESA in place
of text mode (I think I had also started on a native driver for the S3
Virge...).

one noticable observation at the time was that video memory was a lot slower
than native memory, so it was faster to draw everything in a local buffer
and dump it to the screen (computers were not so fast back then).

eventually this project died because I decided it was pointless.

but, oh well...


>>
>> Final warning: this is *so* not a good idea. BAD BAD BAD IDEA, okay? Bad.
>> If you insist on doing this, you will NOT get a biscuit.
>>
>> Nevertheless, if you must do it, that's one way to do it.

>
> There is a reason for it. I need to be able to write explicit 8, 16, 32
> bit values to any address within the 32 bit address space. This is allowed
> on the platform I am writing (32 Bit Pmode under DOS).


yeah...



 
Reply With Quote
 
cr88192
Guest
Posts: n/a
 
      04-27-2008

"santosh" <(E-Mail Removed)> wrote in message
news:fv1b73$j7g$(E-Mail Removed)...
> Yep wrote:
>
>> Ian Collins wrote:
>>> Yep wrote:
>>>> Walter Roberson wrote:
>>>>> That said: you would be better off trying:
>>>>>
>>>>> *(unsigned short *)myaddress=somevalue;
>>>> That works! Why is the extra * needed in front of the cast?
>>>
>>> Maybe writing the expression as
>>>
>>> *((unsigned short *)myaddress) = somevalue;
>>>
>>> makes it clearer?
>>>

>> It does.
>>
>> So its a pointer to the unsigned short, pointed to by myaddress.

>
> I'm not clear about what you are saying above but that line actually
> takes the value of myaddress (which is the address it holds) which of
> type char * and explicitly converts it to a value of type unsigned
> short *, then deferencing this value to write somevalue.
>
>> I did a test case:
>>
>> *((unsigned long *)myaddress) = somevalue; //32 bit
>> *((unsigned short *)myaddress) = somevalue; //16 bit
>> *((unsigned char *)myaddress) = somevalue; //8bit

>
> These are the least sizes that the C standard requires but they *could*
> be bigger on some platforms. At least on the x86_64 under some OSes
> long is actually 64 bits, so you might want to use casts to uint32_t *,
> uint16_t *, and uint8_t * instead of unsigned long *, unsigned short *,
> and unsigned char *. The former are guaranteed to be exactly those
> sizes, without padding bits and in twos-complement format.
>


now, an x86-64 DPMI would be interesting...

actually, I would have liked it had x86-64 come with some way of using the
extended GPRs and XMM regs in 32-bit mode...

actually, I would have also liked it had existing 64 bit OS's come up with
the idea of running drivers in Ring1 or Ring2 connected to a 32-bit stub
kernel, so that 32-bit drivers would still work in long mode...

or, also, a 64-bit "monitor" kernel, with a 32-bit "main" kernel and
drivers, and a mix of 32 bit and 64 bit processes. most of the OS would
remain 32-bit, but then we can start adding 64 bit stuff...

oh well... drivers will catch up with the OS'es and HW...


>> And observed the assembly code generated by the compiler, the behavior
>> is correct.
>>
>> Thank you!!!!!

>



 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
pointers, pointers, pointers... cerr C Programming 12 04-07-2011 11:17 PM
How does one get an absolute absolute file path? James Byrne Ruby 3 09-14-2010 06:02 PM
Pointers to specific memory addresses moschops C++ 11 01-13-2008 07:46 AM
How to implement a firewall for Windows platform that blocks based on Mac addresses instead of IP addresses cagdas.gerede@gmail.com C Programming 1 12-07-2006 04:30 AM
Physical Addresses VS. Logical Addresses namespace1 C++ 3 11-29-2006 03:07 PM



Advertisments