2

I'm trying to write a function which will print message onto the screen using VGA text mode buffer. This is function which prints a single char:

void putc(uint8_t c, enum Color term_color)
{
    uint8_t *vidptr = (uint8_t*)0xB8000;

    *vidptr = c;
    vidptr++;
    *vidptr = (uint8_t*)term_color;
    vidptr++;
}

Here is function which I want to print string:

void puts(const uint8_t* str, enum Color term_color)
{
    for(size_t i = 0; i != '\0'; i++) {
        putc(str[i], term_color);
    }
}

But it doesn't print anything. There is just black screen with blinking cursor.

EDIT: first function which prints a single character works.

msk
  • 141
  • 1
  • 3
  • 11
  • `vidptr` is a local variable in `putc` so the scope of changes only apply while that function is executed and lost afterwards. What happens if you mark it static or move it outside the `putc` function. Since it is memory mapped IO you should use `volatile` as well. Something like `volatile uint8_t * const vidptr = (volatile uint8_t *)0xb8000` outside the function. – Michael Petch May 04 '18 at 12:38
  • 1
    Your `puts()` calls `putc()` but this prints every character into the upper left corner. You somehow have to remember the incremented `vidptr` outside of `putc()`. Try first to make `static uint8_t *vidptr = (uint8_t*)0xB8000;` to understand what I mean. Then, consider that you might want later something like `setCursor()` to (re-)set it to a certain cell. – Scheff's Cat May 04 '18 at 12:38
  • Oops, drop the `const` in my first comment. Usually with text mode on display page 0 I have a main pointer to base of video memory that remains constant and keep track of current X,Y coordinates in global variables. It is often easier to consider text memory as`uint16_t` or even better - a struct to more easily address the color/attribute byte and the color – Michael Petch May 04 '18 at 12:44
  • doesnt 't print anything or prints in 1 place? – Martin Chekurov May 04 '18 at 12:45
  • Are you writing a 32-bit kernel or a 64-bit one? This question may seem irrelevant but it isn't. Often people writing a 64-bit kernel try to compile the code as 64-bit but don't actually place the processor in 64-bit long mode. The result is 64-bit code not being decoded properly. Often manifests itself early in OS development with video routines not working as expected. – Michael Petch May 04 '18 at 12:49
  • I am writing 32-bit kernel and compiling it in nasm with 64-bit option – msk May 04 '18 at 12:53
  • I didn't originally look at the actual code closely enough. In `puts` you have this as a condition: `i != '\0'`. It should be `str[i] != '\0'`? This would be a bug that would prevent `puts` from doing anything since the first time through the loop `i` is 0 and thus nothing will happen. `0 == '\0'` is always true. – Michael Petch May 04 '18 at 13:06

1 Answers1

2

The function

putc(uint8_t c, enum Color term_color)

always put the character in the same position (0xB8000).
You need to declare

uint8_t *vidptr

outside the function to correctly increment it each call.

Lucandroid
  • 56
  • 4
  • 2
    It is a little more than this since the loop he has is wrong `for(size_t i = 0; i != '\0'; i++) ` is incorrect. The condition should be `for(size_t i = 0; str[i] != '\0'; i++) ` – Michael Petch May 04 '18 at 13:14
  • 1
    @Michael Petch, Right! I have seen only the "main" problem. This explains also why no character was shown: the loop does not starts ('\0' is 0)! – Lucandroid May 04 '18 at 13:33