0

I am trying to make a function that would write strings to video memory with a specific color. However, I am unable to make it work. To write single characters, i would do this:

*(char *)0xb8000 = 'O'; //Prints the letter O at the first position in video memory
*(char *)0xb8001 = 'O'; //Adds it some colors (Haven't figured how to write a byte here)

But I need to write with a variable, so I tried this but it just prints nothing.

int currentAddressVRAM = 0xb8000;

*(char *)currentAddressVRAM = 'O';
currentAddressVRAM++;

*(char *)currentAddressVRAM = 'O';
currentAddressVRAM++;

How would I do this? What am I doing wrong?

Edit: I tried this too and it just printed nothing:

char *currentAddressVRAM = (char *)0xb8000;

*currentAddressVRAM = 'O';
currentAddressVRAM++;

*currentAddressVRAM = 'O';
currentAddressVRAM++;
nico_qwer
  • 112
  • 10
  • Are you sure that on the platform you are working on an `int` is large enough to hold `0xb8000`? And why not store a pointer to the VRAM address directly, such as `char *vram = 0xb8000;`? Why store the address in an integer? – UnholySheep Jun 20 '22 at 13:52
  • My environment is this virtual machine (executable) : qemu-system-x86_64. – nico_qwer Jun 20 '22 at 13:54
  • tbh, I don't know how to store the memory adress. I used int because I thought it was logical, but it might not be that – nico_qwer Jun 20 '22 at 13:56
  • Please try the proposed changes (using a wider int and using a pointer) and report the results. Both are plausible enough to merit that effort. – Yunnosch Jun 20 '22 at 14:00
  • In case that 0x8000 is read-writeable (not necessarily legally...) please check whether the `'O'` ends up there. – Yunnosch Jun 20 '22 at 14:03
  • Here you can find information about the color values: https://wiki.osdev.org/Text_UI#Colours – Kolodez Jun 20 '22 at 14:07
  • The color is not the problem. If I make the color : (char)0x0A It still does not work even tho it would be light green on black. – nico_qwer Jun 20 '22 at 14:09
  • How would I make sure that the O ends up there? It runs on an emulator with no OS so I can't use printf to print the value of that place in memory – nico_qwer Jun 20 '22 at 14:12
  • Can you do anything notable? Like shutdown on equality vs. hang on inequality? – Kolodez Jun 20 '22 at 14:17
  • I would expect these codes to be equivalent. Check the assembly code your compiler generates. See what's different. – user253751 Jun 20 '22 at 14:23
  • Can't you move the first to the second character like `*(char *)0xb8002 = *(char *)0xb8000`? – Kolodez Jun 20 '22 at 14:23
  • Maybe this might help- https://stackoverflow.com/a/15638857/19323916 – L_R Jun 20 '22 at 15:21
  • 1
    @Kolodez: No, in C, integer literals have a type wide enough to hold the value. On a system with 16-bit `int`, 0xb8000 would have type `long`. (`unsigned long` is also an option before `long long` for literals with no suffix, or for non-decimal bases). See https://en.cppreference.com/w/c/language/integer_constant – Peter Cordes Jun 21 '22 at 04:32

1 Answers1

3

I found out how to do it finally!
Thanks for all of your helpful comments, it help me find the solution to my problem.
Here is my code :

#define VIDEO_MEMORY 0xb8000

void PrintS(char *text, char color)
{
    char *currentAddressVRAM = (char *)VIDEO_MEMORY;
    for (int i = 0; 1; i++)
    {
        if (text[i] == '\0')
        {
            break;
        }
        *currentAddressVRAM++ = text[i];
        *currentAddressVRAM++ = color;
    }
}

The only problem with this is that I don't know how to save the current address between the uses of the function. If somebody knows, please let me know!

nico_qwer
  • 112
  • 10
  • 1
    A global variable of pointer type would be the obvious choice. Like `struct VGA_char { char txt, attrib;} *cursor = (void*)VIDEO_MEMORY;` – Peter Cordes Jun 21 '22 at 04:28
  • 1
    Your `if()break` could very easily and readably the loop condition inside the for loop, like `for(int i=0 ; text[i] != 0 ; i++) {` – Peter Cordes Jun 21 '22 at 04:30