-1

I was going through the Kernel development tutorials all over the Internet when I found the bona fide OS development tutorials.

I went through the code, but I could not understand this.

The code is as follows :

int main(void){

char *str = "Hello, world", *ch;

unsigned short *vidmem = (unsigned short*) 0xb8000;
unsigned i;

for (ch = str, i = 0; *ch; ch++, i++)
    vidmem[i] = (unsigned char) *ch | 0x0700;

for (;;);
}

When I compiled the above code using Dev C++ and generate a Win32 console or Windows application it crashes when I run it, and it tells me that my program "has stopped working" and terminates. It appears to fail on this line in the loop:

vidmem[i] = (unsigned char) *ch | 0x0700;

What is wrong with the code, and how can I solve the problem?

Michael Petch
  • 46,082
  • 8
  • 107
  • 198
Panther Coder
  • 1,058
  • 1
  • 16
  • 43
  • *it shows error in for statement* is not a problem description. There are *two* for statements - which one is causing the error? And what **exact** error is it showing? You have that information on your screen right in front of you; there is absolutely no reason for you to not include it in your question so we have it as well. – Ken White May 22 '16 at 03:42
  • I am running the program directly on windows. So will there be any problem like accessing illegal memory(memory protection) of 0xB8000. Will windows allow the access? – Panther Coder May 22 '16 at 03:55
  • 2
    No, a Windows program will not support this. Win32 applications do not have access to the video memory directly. It will likely cause the program to fault/crash when it does the update to `vidmem` . Is your real question- Why does my Win32 program crash when run? This code is intended to be used in a bare metal environment or an MS-DOS environment (it would work if compiled with TurboC or Microsoft-C compilers that target DOS and run within a DOS environment or emulator like DosBox) – Michael Petch May 22 '16 at 03:57
  • So, I have to compile the code and create a boot loader to load the file in order to see the output. Right? – Panther Coder May 22 '16 at 04:05
  • Yes, that would be one way to test it. – Michael Petch May 22 '16 at 04:10
  • 1
    Other than finding an old 16-bit C-Compiler from 20+ years ago, and running the executable in Dosbox (if you are on a 64-bit Windows system) -no there is no real easy way. Testing it inside your kernel would probably be best. – Michael Petch May 22 '16 at 04:17

1 Answers1

2

In the the for loop:

for (ch = str, i = 0; *ch; ch++, i++)
    vidmem[i] = (unsigned char) *ch | 0x0700;

the condition portion *chinstructs the C compiler to continue looping while the expressions is true(non-zero). As long as *ch is not a NUL(\0) terminating character the expression will be true and will continue looping. When it reaches a character that is zero the conditional expression will be false and the loop exits. Effectively it loops through a string until it reaches the NUL terminating character.

The reason for your crash with vidmem[i] = (unsigned char) *ch | 0x0700; is because vidmem was given the video memory address 0xb8000. This memory is not accessible to a Win32 based application and the OS (Windows) will fault your application and display the error message about the program no longer working.

The only way to resolve this is compile it in such a way that it can be used as an MS-DOS program:

  • Compile with 16-bit C compiler and run it in MS-DOS or an MS-DOS emulator like DosBox
  • Compile it into your kernel and test it in a bare metal environment (QEMU, Virtualbox, VMWare etc.)

*ch | 0x0700 takes the current character and bitwise ORs it to 0x0700. That effectively creates a 16-bit word with the character in the lower 8 bits and 0x07 in the upper 8 bits.

This is done because every character you see on standard color text video modes that use memory region 0xb8000 is made up of 2 bytes (one 16-bit word). This is described in a Wikipedia article:

Video memory cell

If the current character being processed in the loop is the letter H (0x48) then *ch | 0x0700 would become 0x0748 which is then stored at a particular memory location on the video display.

You may wish to read about bit manipulation in C. I found this tutorial that may help.

Michael Petch
  • 46,082
  • 8
  • 107
  • 198
  • There is an Bitwise OR separating the character and attribute why? – Panther Coder May 22 '16 at 04:42
  • @PantherCoder I've updated my answer a bit to touch on that and a link to a tutorial about bit manipulation in _C_ – Michael Petch May 22 '16 at 04:50
  • vidmem[0] points to address 0xB800. Will it store 8bits in it or store 16bits since it is protected mode code? – Panther Coder May 23 '16 at 05:58
  • @PantherCoder vidmem It is defined as an an unsigned short * which act like the pointer to an array of unsigned short int . Thus vidmem[i]= will treat each element as an unsigned short int. An unsigned short in your compiler is 2-bytes wide (16-bit integer) so it will store 2 bytes with each assignment – Michael Petch May 23 '16 at 11:53