Search code examples
cosdev

Function receiving null string


I have the following problem: I pass a string to a function, however, when it receives the string, it receives a null value and does nothing, I've been trying to solve it for days and nothing, I'm thinking it's a error in main() function

Here is my code:

void main(){
   clear_screen();
   print_string("Hello World!"); 
}


void print_string(const char *string){
   int offset = get_cursor();
   int i = 0;
   while (string[i] != 0) {
      if(offset >= ROWS * COLS * 2) {
         offset = scroll_line(offset);
      }
      if(string[i] == '\n') {
         offset = move_offset_to_new_line(offset);
      }else{
         print_char(string[i], offset);
         offset += 2;
      }
      i++;
   }
   set_cursor(offset);
}

What can be happening in my code? Note: I'm following the example on this site: https://dev.to/frosnerd/writing-my-own-boot-loader-3mld


Solution

  • Summarizing discussion from comments:

    The bootloader code in this example (not in the question but in the linked site) is hardcoded to load the kernel by reading 2 sectors from the disk. So this will only work if the kernel image is less than 1 KB in size. With your modified code, your image turned out to be more than 1 KB (8 KB in fact). So you weren't loading all of it, and in particular you weren't loading the part of the image that contained your string literal. Thus when you accessed it, you got the contents of uninitialized memory, which apparently began with a zero byte, giving you the equivalent of an empty string.

    You'll need to keep track of the size of your kernel image as you write more code and keep the bootloader in sync: look at the mov dh, 2 following load_kernel and replace 2 by the appropriate number of 512-byte sectors. For a more serious project, you'd want to come up with a more robust mechanism: e.g. the first sector of the kernel image could contain a header which specifies how many more sectors to read.

    Most compiler and linker setups will place string literals into a read-only data section (e.g. .rodata), separate from the code section (.text), and will arrange for each section to occupy a second set of 4 KB pages, so that page-granular memory permissions can be set accordingly (read and execute for .text, read and no execute for .rodata). So even if your code and data could have fit in 1 KB, the need to put the code and data on separate pages is likely what accounts for the 8 KB file size (2 * 4 KB). If you add read-write data (e.g. a global variable which isn't const), you'll probably see another 4 KB increase.