1

I have got some problem with memory access and postix incrementation :/
I need to access to video memory at boot, thus, I create a pointer to 0xB8000 address and then, I increment the pointer to access next location.

Basically, the code would be :

volatile char *p = (volatile char *)0xB8000;

for (int i = 0; i < 5; ++i)
    *(p++) = 'A';

This way, p point to the proper memory address, and after each access, it is incremented (I know, the there is 2 bytes for each character displayed, but here is not the problem).

But this doesn't work, no character displayed. It display nothing. But if I change incrementation to prefix like this, it works, i can see the characters on the screen !

volatile char *p = (volatile char *)0xB8000;

for (int i = 0; i < 5; ++i)
    *(++p) = 'A'

So, I checked assembly code :

; Postfix
mov ecx, DWORD PTR _p$[ebp]
mov BYTE PTR [ecx], 65       ; 'A' character
mov edx, DWORD PTR _p$[ebp]
add edx, 1
mov DWORD PTR _p$[ebp], edx

; Prefix
mov ecx, DWORD PTR _p$[ebp]
add ecx, 1
mov DWORD PTR _p$[ebp], ecx
mov edx, DWORD PTR _p$[ebp]
mov BYTE PTR [edx], 65       ; 'A' character

I can't spot the difference. By the way, I could use the prefix incrementation but, I would like to understand with does the postfix not work :/

The assembly code is from Visual C++ compiler, I don't have any GCC at work :/

EDIT : I know the difference between prefix and postfix incrementation, and I see the difference between assembly code present here. But IMO, none of these differences leads to non printing characters on screen.
About the attribute byte : I know I should set it properly. I would keep a light example with light assembly code, but actually, with incrementation the attribute character is always set to 'A' wich lead to a blue letter on a red background.

Thank you :)

Quentin
  • 724
  • 7
  • 16
  • ++p increments, then reads/writes. p++ reads/writes, then increments. It's the order. If I do int a = 4; int b = ++a; then b will be 5. If I do int b = a++; instead b will be 4. – B. Nadolson Aug 27 '15 at 08:43
  • You can't spot the difference? I can. The second example increments the `p` one time too often. And in assembly you also can see the difference. First example writes `A` first and then increments and second example increments first and writes then `A` – ckruczek Aug 27 '15 at 08:43
  • 2
    Why do you think there is no difference ? There is difference read carefully your assembly code. – ameyCU Aug 27 '15 at 08:44
  • Weird. The assembly looks as it just does what it should. Postfix increments after writing the character, Prefix increments before writing the character. Are you sure your video memory isn't made from big-endian shorts? – St0fF Aug 27 '15 at 08:45
  • Maybe this will help *you* see the difference: http://stackoverflow.com/questions/7031326/what-is-the-difference-between-prefix-and-postfix-operators – CinCout Aug 27 '15 at 08:46
  • 1
    The video memory uses two bytes per character, one for selecting the glyph and one for the color. If any of them is not set, there will be either a blank character or a **black** character. Both are invisible! – Bo Persson Aug 27 '15 at 08:50
  • Thank you but I know the different increment operator and how they work, my problem is not here, I see the difference between assembly code, but not the difference that lead to not see characters on the screen. ;) @St0fF I tought about it, but the prefix incrementation works perfectly, with big-endian shorts, it would not :/ – Quentin Aug 27 '15 at 08:52
  • 2
    "*there is 2 bytes for each character displayed, but here is not the problem*". Are you sure this is not the problem? Because the difference is that you are *not writing the attribute byte* for the first character in the post-increment case (and instead write the attribute byte for the third char). – dhke Aug 27 '15 at 08:54
  • @BoPersson You're right, actually, in my code, the attribute bytes are set, I didn't set them on the example the get a light assembly code. By the way, If i the set attrbute character (like in the example) with 'A', it lead to a blue letter on a red background, so, we could se that the affectation is working. – Quentin Aug 27 '15 at 08:59
  • @naccyde: You misunderstood. I didn't know about the atttribute byte, but I meant that: maybe the second byte per each on-screen-character is the glyph? (In my thinking I imagined the first byte to be some hi-byte of a 16bit glyph set) – St0fF Aug 27 '15 at 09:02
  • @naccyde - So you have problems with *some other code* that you are not showing? Then how can we help you, if you don't show the *real* problem? – Bo Persson Aug 27 '15 at 09:12
  • @St0fF I'm not sure to uderstand exactly what the glyph is (the character representation ? So character coded on 16 bits ?), but for `*p = 'A'; p++; *p = 0x77; *p++` it works, so it access byte per byte to the memory, and the displayed character is displayed with correct attributes. In case of 16 glyph set, the `*p = 0x77;` would fill the lower bits of the glyph, so, not display 'A', and not use 0x77 as the attributes. – Quentin Aug 27 '15 at 09:16
  • @BoPersson The "some other code" you mention here is affecting attribute byte a value, like `*(p++) = 0x77;`, that does not change many things and lower the C and assembly readability. I tried with the code I posted, it should show three 'A' letters on top left of the screen in blue with a red background. It doesn't show anything. – Quentin Aug 27 '15 at 09:20
  • @naccyde - I asked for the *real* code, because it is very common for people who don't see exactly what happens to accidentally remove the actual problem when trying to simplify the code. We get working code posted here every single day, with "why doesn't this code work". :-) – Bo Persson Aug 27 '15 at 09:29
  • @BoPersson You're right, I'll update my post later, when I'll have access to the exact code so ;) – Quentin Aug 27 '15 at 09:33
  • @naccyde: what's so unbelievable in having a charset of at max 65536 characters (glyphs)? Provided that I was concerned only with the language C, not with the actual video memory problem (i.e. not knowing about the attribute byte, just seeing that a write one memory position further worked), my thoughts seem not far-fetched. You simply try to interpret even more into my questions. I actually remember video chips that had "do it, do it now!"-registers. Those had to be written twice to show some effect (yes, the commodore 128 VDC chip was such one). – St0fF Aug 27 '15 at 11:15
  • @St0fF - the total BIOS size for a CGA adapter is not even 64kb. The size of a 1990 era VGA bios was in the order of 32kb - 7 bit chars were the norm for an awfully long time. 8 bit chars gave us the extended ASCII set. Perhaps not common knowledge, but hardly obscure either. I wouldn't term your thoughts as `far-fetched`, but think `ill-considered` wouldn't be unfair. ;) More here: http://www.minuszerodegrees.net/rom/rom.htm – enhzflep Aug 27 '15 at 11:48
  • @St0fF : I understand what you say, and yes, 65536 characters charset are not unbelievable. But once again, when affecting a char to a memory location with postfix incrementation (`*(p++) = 'c';`), it does not work, but, the same code with later incrementation works (`*p = 'c'; p++;`). So, the memory location is the same, in both case I write only one time, etc... For me, these situation are the same (as `p += 1` and `p = p +1`, same operation, diffrente way to write it). – Quentin Aug 27 '15 at 11:52
  • @enhzflep What is the relationship between BIOS size and number of character glyphs ? – fjardon Aug 27 '15 at 12:13
  • @fjardon - the character glyphs are stored as 1-bit bitmaps in the (video) BIOS ROM. For an 8x8 pixel font, you need 8 bytes of storage to hold the glyph of each character. See the problem yet? If not, there's more here: http://www.shikadi.net/moddingwiki/B800_Text – enhzflep Aug 27 '15 at 12:16
  • @enhzflep I still don't see why it must be in the BIOS rom. Whatever ROM would do. Indeed I'm pretty sure the original XT did have the character ROM connected solely to the character generator IC. And still I don't see a relationship between BIOS size and number of character glyphs. I agree that some characters may end up with the same glyphs *by default*, but one could devise a paging mechanism to allow the programmer to customize *some* pages in RAM. – fjardon Aug 27 '15 at 13:05
  • @fjardon - for the same reason that the engine of a car is in the car, not towed in a detacheable trailer behind it. The two of them are basically useless without one-another. ROM is simply read-only-memory. In the case of the BIOS, it performs a number of functions. It stores the images of the glyphs used in text modes, it also contains all of the code used to drive the video card's basic functions. It contains routines for (amongst other things) setting the video mode, outputting characters, bank-switching, timing and in the case of newer BIOSes, line drawing and even figure filling routines – enhzflep Aug 27 '15 at 13:17
  • @fjardon - in fact, through the mechanism of ROM BIOS shadowing, the system BIOS copied the BIOSes from the various adapters in the system into much faster RAM and mapped access intended for the actual adapter BIOS to this much faster RAM. One of the lovely side-effects of this was the glyphs were no longer held in unmodifiable memory - this allowed one to redefine the glyphs used for text output when in the various text modes. In the 90s I used to write code that overwrote the default font with one I found better to program with. It was fun to swap _some_ glyphs on friends PCs. :evil-grin: – enhzflep Aug 27 '15 at 13:24
  • 2
    @enhzflep http://www.minuszerodegrees.net/oa/OA%20-%20IBM%20Color%20Graphics%20Monitor%20Adapter%20(CGA).pdf (IBM CGA Technical Refrence), clearly states that: `A ROS character generator is used with 8K bytes of storage that cannot be read from or written to under program control.`. So it clearly is *not* part of the BIOS. – fjardon Aug 27 '15 at 13:31
  • @fjardon - Good catch. Thanks for correcting my rusty memory. – enhzflep Aug 27 '15 at 13:43

1 Answers1

0

After a few more tests, I found the possible cause of this error, it was about the .rodata section not properly linked, so it's now better.

For more details, I follow some of the instructions availables on an OSDev Tutorial ;)

Quentin
  • 724
  • 7
  • 16