By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,853 Members | 958 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,853 IT Pros & Developers. It's quick & easy.

Accessing memory at 0xb800

P: n/a
Hi,

I'm trying to access memory directly at 0xb800 (text screen). I tried this:

char far* screen = (char far*)0xb8000000;

but apparently c++ compiler doesn't know "far" (says "syntax error
before *"). I've tried using __far, _far, FAR, _FAR, and __FAR, all with
the same result. So, then I tried this:

char* screen = (char*)0xb8000;

This compiles fine, but when I try to access it with screen[0]='a', it
gives me segmentation fault. Anyone knows what's wrong with it?
I'm using c++ v3.2.2 that came with my linux box.

Thanks
luph

Jul 22 '05 #1
Share this Question
Share on Google+
13 Replies


P: n/a
lupher cypher wrote in news:ww**************@nwrdny02.gnilink.net:
Hi,

I'm trying to access memory directly at 0xb800 (text screen). I tried
this:
Don't do this use a library that comes with your system to write to
the screen.

char far* screen = (char far*)0xb8000000;
Well if you were running ms-dos and had a sutible compiler then this
would work.

but apparently c++ compiler doesn't know "far" (says "syntax error
before *"). I've tried using __far, _far, FAR, _FAR, and __FAR, all
with the same result. So, then I tried this:

char* screen = (char*)0xb8000;

This compiles fine, but when I try to access it with screen[0]='a', it
gives me segmentation fault. Anyone knows what's wrong with it?
I'm using c++ v3.2.2 that came with my linux box.


The real question is, Why are you trying to do this ? If it some code
you found in a text book, the book is 1) very old and 2) not applicable
to your OS (linux).

here is a man page for curses which might help:

http://docsrv.caldera.com:507/en/man.../curses.S.html

For better advice ask in a newsgroup that supports your platform
and/or your compiler, there is alas no standard way of writing
directly to the screen.

HTH.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 22 '05 #2

P: n/a
lupher cypher wrote:
Hi,

I'm trying to access memory directly at 0xb800 (text screen). I tried this:

char far* screen = (char far*)0xb8000000;

but apparently c++ compiler doesn't know "far" (says "syntax error
before *"). I've tried using __far, _far, FAR, _FAR, and __FAR, all with
the same result. So, then I tried this:
"Far" is a kludge to get around pointers that aren't big enough; I've
only needed it on 8-bit microcontrollers and 16-bit x86 chips. If your
system is running linux, you should never need to use "far" again.
char* screen = (char*)0xb8000;
I'm pretty sure that's not the address you mean.
This compiles fine, but when I try to access it with screen[0]='a', it
gives me segmentation fault. Anyone knows what's wrong with it?
I'm using c++ v3.2.2 that came with my linux box.
It sounds like that's not an address you own. Where did you come up
with that pointer value? Also, why do you sometimes write 0xb8000000,
sometimes 0xb800, and other times 0xb8000? Your pointers are probably
thirty-two bits wide; are you assuming that the literal value is being
zero-extended on one side?

-Jeff

Thanks
luph


Jul 22 '05 #3

P: n/a
On Wed, 24 Dec 2003 21:37:08 -0500, Jeff Schwab <je******@comcast.net>
wrote:
lupher cypher wrote:
Hi,

I'm trying to access memory directly at 0xb800 (text screen). I tried this:

char far* screen = (char far*)0xb8000000;

but apparently c++ compiler doesn't know "far" (says "syntax error
before *"). I've tried using __far, _far, FAR, _FAR, and __FAR, all with
the same result. So, then I tried this:


"Far" is a kludge to get around pointers that aren't big enough; I've
only needed it on 8-bit microcontrollers and 16-bit x86 chips. If your
system is running linux, you should never need to use "far" again.
char* screen = (char*)0xb8000;


I'm pretty sure that's not the address you mean.
This compiles fine, but when I try to access it with screen[0]='a', it
gives me segmentation fault. Anyone knows what's wrong with it?
I'm using c++ v3.2.2 that came with my linux box.


It sounds like that's not an address you own. Where did you come up
with that pointer value? Also, why do you sometimes write 0xb8000000,
sometimes 0xb800, and other times 0xb8000? Your pointers are probably
thirty-two bits wide; are you assuming that the literal value is being
zero-extended on one side?


Even assuming that the display is memory mapped the way that old DOS
systems were, and even assuming the screen is actually in text mode
you still have serious problems.

Protected operating systems (using CPU chips that support it) control
just who gets to read and write which memory. You don't "own" the
memory that is not allocated to your process so you can't read or
write it.

Some operating systems might notice that you are trying to read or
write that location and guess that you might be trying to access the
screen and do what is necessary to make things work. But that is only
true for systems that must support old DOS programs. We are not in
DOS-land anymore, though.
Jul 22 '05 #4

P: n/a
lupher cypher wrote:
Hi,

I'm trying to access memory directly at 0xb800 (text screen). I tried
this:

char far* screen = (char far*)0xb8000000;

but apparently c++ compiler doesn't know "far" (says "syntax error
before *"). I've tried using __far, _far, FAR, _FAR, and __FAR, all with
the same result. So, then I tried this:
Run off. Anything to do with "far,huge,small" in conjunction with pointers
is going to be old code and useless to you.
char* screen = (char*)0xb8000;

This compiles fine, but when I try to access it with screen[0]='a', it
gives me segmentation fault. Anyone knows what's wrong with it?
Machines without hardware protection (or with it turned off) let a program
access anything anywhere, whether it exists or not. Consider your program
doing its thing then another came along and did the same. Something's gotta
give. Such code falls under the realm of "device drivers" - one thing (or a
chain of them) has responsibility for talking to your hardware. Those will
provide "standard" (for your system) interfaces (probably at varying
levels) through which you can talk to them.
I'm using c++ v3.2.2 that came with my linux box.


"man curses/ncurses" for text. For graphics, well there's lots. SDL you can
draw on (games) and things like wxwindows for apps that want gui's. All
these are offtopic here though because they're language add-ons. The ones
I've mentioned are available for windows as well.
--
Guy Harrison
Jul 22 '05 #5

P: n/a
On Thu, 25 Dec 2003 01:59:56 +0000, lupher cypher wrote:
I'm trying to access memory directly at 0xb800 (text screen). I tried this:

char far* screen = (char far*)0xb8000000;

but apparently c++ compiler doesn't know "far" (says "syntax error
before *"). I've tried using __far, _far, FAR, _FAR, and __FAR, all with
the same result. So, then I tried this:

char* screen = (char*)0xb8000;

This compiles fine, but when I try to access it with screen[0]='a', it
gives me segmentation fault. Anyone knows what's wrong with it?
I'm using c++ v3.2.2 that came with my linux box.


This worked under DOS, but does not work under any modern OS. The reason
is that modern CPUs (well modern for microchips, all other CPUs already
had this) have memory management. That means that the view your program
has of the memory has nothing to do with the real layout of the memory.

The big advantages of this are:

- Your program is isolated from other processes, one ill behaving program
cannot take down the whole OS or other programs.

- Your OS can fake more memory than there really is, it uses harddisk
storage for this (swapfile or swappartition)

- Programs are not allowed to access hardware directly, they must use the
OS to access the hardware. This makes it possible for multiple programs to
use the same hardware.

The disadvantage is that you cannot access hardware directly (hey, that
was also an advantage!), you must write a devicedriver to do that.
Luckily, more often than not, others have already done that. And often
complete libraries are written to make using this easier. As you use
Linux, have a look at the ncurses library.

BTW, ncurses is off topic for this group, if you have any questions about
that, please ask in a linux/posix group.

HTH,
M4

Jul 22 '05 #6

P: n/a
>>
I'm trying to access memory directly at 0xb800 (text screen). I tried
this:
but apparently c++ compiler doesn't know "far" (says "syntax error
before *"). I've tried using __far, _far, FAR, _FAR, and __FAR, all
with the same result. So, then I tried this:

char* screen = (char*)0xb8000;

This compiles fine, but when I try to access it with screen[0]='a', it
gives me segmentation fault. Anyone knows what's wrong with it?
I'm using c++ v3.2.2 that came with my linux box.

The real question is, Why are you trying to do this ? If it some code
you found in a text book, the book is 1) very old and 2) not applicable
to your OS (linux).


Well, it's not from a book, and I need to redraw text screen without
"scrolling" it each time (outputting all 25 lines to redraw). So, I
figured it's easier to simply draw on the screen directly into memory. I
also need to save the whole screen into a buffer and then flush it back out.

here is a man page for curses which might help:

http://docsrv.caldera.com:507/en/man.../curses.S.html
I've tried this, but although it is something like I need, it gives me
errors (e.g. when I use mvaddch, it would say that waddch and a couple
of other functions are undefined).

For better advice ask in a newsgroup that supports your platform
and/or your compiler, there is alas no standard way of writing
directly to the screen.


Hmm.. How about through hardware interrupt 10? :) Unless linux has some
protection against that, but I wouldn't think so..

luph

Jul 22 '05 #7

P: n/a
Jeff Schwab wrote:
char* screen = (char*)0xb8000;


I'm pretty sure that's not the address you mean.


Well, the text video memory resides at b800:0000, so 0xb8000 would be
the absolute address in memory..
This compiles fine, but when I try to access it with screen[0]='a', it
gives me segmentation fault. Anyone knows what's wrong with it?
I'm using c++ v3.2.2 that came with my linux box.

It sounds like that's not an address you own. Where did you come up
with that pointer value? Also, why do you sometimes write 0xb8000000,
sometimes 0xb800, and other times 0xb8000? Your pointers are probably
thirty-two bits wide; are you assuming that the literal value is being
zero-extended on one side?


Well, I don't know that much about linux, but it should be pretty much
the same as in windows in this case - we can open several terminals when
we run gui, so I assume every terminal process gets it's own chunk of
memory and when I try to access segment b800, it simply works it out.
But that should be owned by me anyhow then.. As for writing it in
different ways - I was looking online to find a way to write there, and
there were several different codes, so I tried them all :)
I was a bit confused by 0xb8000000 myself, because that's not the way it
should be, but then I though maybe it's something about a particular
compiler. For all I know to get the absolute address from a relative
one, we shift segment left 4 bits and then add offset.
By the way, I saw code for linux somewhere where someone was trying to
access a000:0000 (apparently successfully from what I understood), which
is graphic video memory :)

luph

Jul 22 '05 #8

P: n/a
Even assuming that the display is memory mapped the way that old DOS
systems were, and even assuming the screen is actually in text mode
you still have serious problems.
Why shouldn't it be? I thought that's a standard. I recall taking a
class on OS and hardware, and I think it's the video card who simply
compies the whole screen from there to the screen using DMA.. Not
complitely sure about it, but I think that's what we were talking about,
so that CPU doesn't get involved and waste time for the whole thing.
Protected operating systems (using CPU chips that support it) control
just who gets to read and write which memory. You don't "own" the
memory that is not allocated to your process so you can't read or
write it.


Ok, but how would a library like curses read and write from/to the
screen? There should be a way.. I was thinking maybe I should try doing
it through int 10h.. Although first I'll have to figure out how to
insert asm code into c++ programs :)
luph

Jul 22 '05 #9

P: n/a
lupher cypher wrote:
I've tried this, but although it is something like I need, it gives me
errors (e.g. when I use mvaddch, it would say that waddch and a couple
of other functions are undefined).
Lupher, it's going to be a lot easier to fix those errors than to
rewrite the library.

For better advice ask in a newsgroup that supports your platform
and/or your compiler, there is alas no standard way of writing
directly to the screen.

Hmm.. How about through hardware interrupt 10? :) Unless linux has some
protection against that, but I wouldn't think so..


What is "hardware interrupt 10?"

luph


Jul 22 '05 #10

P: n/a
lupher cypher wrote:
Even assuming that the display is memory mapped the way that old DOS
systems were, and even assuming the screen is actually in text mode
you still have serious problems.

Why shouldn't it be? I thought that's a standard. I recall taking a
class on OS and hardware, and I think it's the video card who simply
compies the whole screen from there to the screen using DMA.. Not
complitely sure about it, but I think that's what we were talking about,
so that CPU doesn't get involved and waste time for the whole thing.


So, you think your code is running on the video card? Far-out system,
man. My code runs on my lamp.
Protected operating systems (using CPU chips that support it) control
just who gets to read and write which memory. You don't "own" the
memory that is not allocated to your process so you can't read or
write it.

Ok, but how would a library like curses read and write from/to the
screen? There should be a way..


No, there shouldn't; at least, not without such I/O being gated by the
kernel.
I was thinking maybe I should try doing
it through int 10h.. Although first I'll have to figure out how to
insert asm code into c++ programs :)
I think I've figured out what you meant by "hardware interrupt 10,"
thanks to this site (thank you Google):

http://www.cs.umbc.edu/courses/under...ts.html#int10h

FYI, "10h" isn't a standard hardware interrupt, it's a BIOS interrupt.
Unless you're hacking your kernel, kiss your BIOS interrupts goodbye,
and good riddance. The equivalent in Linux is a request to the kernel,
known as a "system call," which manifests itself as a call to a C function.

Most processors won't let you write to addresses you don't own because
your code is not "privileged," meaning the chip is not in a sufficiently
"privileged mode." The kernel is privileged because it was loaded
specially when your system was started. If you want your code to run in
a privileged mode, you basically have to write your own kernel (or hack
the existing one). You are more than welcome to try these options. Try
Googling for "boot loader."

Anyway, it sounds like you are very familiar with a particular
programming environment. Unfortunately, that particular environment is
generally deemed "crappy." Since you are running Linux now, you have
access to a truck-load more functionality than you probably realize.

So, here's my advice:

1) Forget basically every low-level detail you've learned about your
system. You don't need to know any of that anymore.

2) Learn to write programs that rely only on standard C++, or whatever
subset is offered by the best compiler available to you. It's okay to
cheat a little by using bash scripts to call your programs in particular
ways, e.g. in a graphical terminal emulator.

3) When you want to do something not provided by the C++ standard
library, find an existing library to do it for you. If you have trouble
compiling it (as you did with Curses), track down the problems in the
code and fix them yourself. Notify the maintainer of the library of
what you did and why.

4) When you need some functionality not found in any existing library
for your system, and you can't adapt a library from a different system
to meet your needs, try writing a new library yourself. Put it under an
open-source license like GPL, and make it available to others. Post an
announcement about it in one of the "comp.your.system.announce" news groups.

5) When you're really stuck trying to make your system do what you want,
post questions to a news group that has specific expertise about your
platform, e.g. the comp.os.linux family.

6) When you want to discuss the C++ language, post here.


luph


Good luck,
Jeff

Jul 22 '05 #11

P: n/a
lupher cypher <lu***********@verizon.net> writes:
Even assuming that the display is memory mapped the way that old DOS
systems were, and even assuming the screen is actually in text mode
you still have serious problems.
Why shouldn't it be? I thought that's a standard. I recall taking a
class on OS and hardware, and I think it's the video card who simply
compies the whole screen from there to the screen using DMA.. Not
complitely sure about it, but I think that's what we were talking
about, so that CPU doesn't get involved and waste time for the whole
thing.


No. It's only needed on operating systems that don't provide proper
device drivers to do this for you.
Protected operating systems (using CPU chips that support it) control
just who gets to read and write which memory. You don't "own" the
memory that is not allocated to your process so you can't read or
write it.


Ok, but how would a library like curses read and write from/to the
screen? There should be a way.. I was thinking maybe I should try
doing it through int 10h


The way it's done on Linux (and most UNIX systems) is through device
drivers. Have a look under /dev at:
/dev/tty?? and /dev/vc/* (both are virtual terminals)
/dev/console (system console)
/dev/pts/* (pseudo or virtual terminals, used by xterm, screen,
ssh etc.)
These are all various terminal device drivers. Try this:

$ tty
/dev/pts/0
$ echo 'hello' > /dev/pts/0
hello

This "device node" is your "gateway" to the hardware. In this case,
you are sending it plain text, but terminal devices also support ANSI
escape sequences for colour, underlining, and other features through
ioctls. This is what ncurses is using to do its stuff with. Try
again with some of the others.

When you run a C++ program, this is where everything you send to
std::cout and std::cerr actually ends up. You can also open them in
your program (providing you have the appropriate permissions).

Notice how we get hardware access in our program without any need for
assembler or direct access with pointers! This is a good thing--it
allows resource sharing, ease of writing portable code, simpler code,
no hardware knowledge required.
.. Although first I'll have to figure out how
to insert asm code into c++ programs :)


Ugh. Just use "plain" C++ as well as the appropriate system library
([n]curses)!
HTH,
Roger

--
Roger Leigh

Printing on GNU/Linux? http://gimp-print.sourceforge.net/
GPG Public Key: 0x25BFB848. Please sign and encrypt your mail.
Jul 22 '05 #12

P: n/a
In article <tu***************@nwrdny02.gnilink.net>, lupher cypher wrote:
Even assuming that the display is memory mapped the way that old DOS
systems were, and even assuming the screen is actually in text mode
you still have serious problems.


Why shouldn't it be? I thought that's a standard. I recall taking a
class on OS and hardware, and I think it's the video card who simply
compies the whole screen from there to the screen using DMA.. Not
complitely sure about it, but I think that's what we were talking about,
so that CPU doesn't get involved and waste time for the whole thing.
Protected operating systems (using CPU chips that support it) control
just who gets to read and write which memory. You don't "own" the
memory that is not allocated to your process so you can't read or
write it.


Ok, but how would a library like curses read and write from/to the
screen? There should be a way.. I was thinking maybe I should try doing
it through int 10h.. Although first I'll have to figure out how to
insert asm code into c++ programs :)

It uses well defined APIs/system calls. These eventually end up in the
kernel, and the appropriate device driver. You cannot get around this,
atleast not without writing kernel code. You can ofcourse
use the very low level system calls to do it though. But
why ? Why won't you use e.g. curses ?

--
Nils Olav Selåsdal <NO*@Utel.no>
System Developer, UtelSystems a/s
w w w . u t e l s y s t e m s . c o m

Jul 22 '05 #13

P: n/a
lupher cypher <lu***********@verizon.net> wrote in message news:<9p****************@nwrdny01.gnilink.net>...
Jeff Schwab wrote:
char* screen = (char*)0xb8000;


I'm pretty sure that's not the address you mean.


Well, the text video memory resides at b800:0000, so 0xb8000 would be
the absolute address in memory..
This compiles fine, but when I try to access it with screen[0]='a', it
gives me segmentation fault. Anyone knows what's wrong with it?
I'm using c++ v3.2.2 that came with my linux box.

It sounds like that's not an address you own. Where did you come up
with that pointer value? Also, why do you sometimes write 0xb8000000,
sometimes 0xb800, and other times 0xb8000? Your pointers are probably
thirty-two bits wide; are you assuming that the literal value is being
zero-extended on one side?


Well, I don't know that much about linux, but it should be pretty much
the same as in windows in this case - we can open several terminals when
we run gui, so I assume every terminal process gets it's own chunk of
memory and when I try to access segment b800, it simply works it out.


What you say is true only if your program is an MS-DOS program, and even
then it works not because your program is writing to the real hardware
video buffer, but rather a simulated one -- part of a "virtual MS-DOS
machine" created by the operating system.

The x86 family of processors support a number of different memory
addressing modes. The mode used in MS-DOS (and the only mode supported
by the 8088 chip used in the original IBM PC) is called real mode. In
this mode, the processor translates a segment:offset address to a 20-bit
physical address by shifting the segment address left 4 bits and adding
the offset. Thus, b800:0000 maps to 0xb8000, which happened to be the
address of the memory-mapped video buffer in text mode.

However, an MS-DOS program running under Windows executes in a different
mode called virtual 8086 mode. Under this mode, a segment:offset address
is first translated to a 20-bit address as described above. However, this
address is not a physical address, but a so-called linear address. The
CPU then references a set of lookup-tables (called page tables) to convert
the linear address to a physical address. This level of indirection
enables the operation system (which maintains the page tables) to create
a separate 1MB address space for each MS-DOS application.

Of course, MS-DOS applications expect to have direct access to hardware
and expect certain addresses to be "special" -- e.g., the video buffer,
the interrupt table, etc. The operating system simulates this by trapping
certain kinds of memory access. Thus, while your MS-DOS application THINKS
it is writing directly to the video buffer, it's actually just writing to
ordinary memory. The operating system detects this and updates the display
accordingly.

This magic exists solely to preserve compatibility with ancient MS-DOS
applications. There's no reason to believe that that the same thing would
work for other types of applications or under other operating systems.
For example, if you tried to write to linear address 0xb8000 in a Win32
application, there's no reason to suppose anything useful would happen.
Modern operating systems provide higher-level, hardware-independent
methods of accessing resources such as the console.
Jul 22 '05 #14

This discussion thread is closed

Replies have been disabled for this discussion.