Help with pointers and absolute memory addresses

Discussion in 'C Programming' started by Ian Collins, Apr 27, 2008.

  1. Ian Collins

    Ian Collins Guest

    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.
    Ian Collins, Apr 27, 2008
    #1
    1. Advertising

  2. In article <4814093c$0$17511$>,
    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
    Walter Roberson, Apr 27, 2008
    #2
    1. Advertising

  3. Ian Collins

    Yep Guest

    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.
    Yep, Apr 27, 2008
    #3
  4. Ian Collins

    Ian Collins Guest

    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.
    Ian Collins, Apr 27, 2008
    #4
  5. Ian Collins

    Yep Guest

    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).
    Yep, Apr 27, 2008
    #5
  6. Ian Collins

    Yep Guest

    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?
    Yep, Apr 27, 2008
    #6
  7. Ian Collins

    Yep Guest

    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!!!!!
    Yep, Apr 27, 2008
    #7
  8. Ian Collins

    santosh Guest

    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!!!!!
    santosh, Apr 27, 2008
    #8
  9. Ian Collins

    cr88192 Guest

    "Yep" <yep@yep> wrote in message
    news:48141ac4$0$1025$...
    > 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...
    cr88192, Apr 27, 2008
    #9
  10. Ian Collins

    cr88192 Guest

    "santosh" <> wrote in message
    news:fv1b73$j7g$...
    > 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!!!!!

    >
    cr88192, Apr 27, 2008
    #10
  11. Ian Collins

    Ian Collins Guest

    cr88192 wrote:
    >
    > 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...
    >

    Considering (at least in the *nix wold) how quickly drivers have been
    ported to 64 bit, that would have been wasted effort.

    Throw someone a life-line, they'll cling on to it, make them swim and
    they'll swim!

    --
    Ian Collins.
    Ian Collins, Apr 27, 2008
    #11
  12. Ian Collins

    cr88192 Guest

    "Ian Collins" <> wrote in message
    news:...
    > cr88192 wrote:
    >>
    >> 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...
    >>

    > Considering (at least in the *nix wold) how quickly drivers have been
    > ported to 64 bit, that would have been wasted effort.
    >
    > Throw someone a life-line, they'll cling on to it, make them swim and
    > they'll swim!
    >


    we still have problems in windows land, and when forced to rely on
    crufted-over windows drivers...


    > --
    > Ian Collins.
    cr88192, Apr 28, 2008
    #12
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. TTroy

    Why do people call addresses "pointers"?

    TTroy, Jan 31, 2005, in forum: C Programming
    Replies:
    49
    Views:
    901
    Romeo Colacitti
    Feb 6, 2005
  2. namespace1
    Replies:
    3
    Views:
    890
  3. moschops
    Replies:
    11
    Views:
    2,306
    Rahul
    Jan 13, 2008
  4. cerr

    pointers, pointers, pointers...

    cerr, Apr 7, 2011, in forum: C Programming
    Replies:
    12
    Views:
    669
  5. James Byrne
    Replies:
    3
    Views:
    550
    James Byrne
    Sep 14, 2010
Loading...

Share This Page