Home > Mobile >  Iterating over string returns empty in c (os development)
Iterating over string returns empty in c (os development)

Time:01-25

I was making an os, or atleast trying to, but I stumbled upon a problem. While trying to iterate over a string to convert to char to print to screen, the returned char seemed to be empty!(I am actually new to os development); Here is the code snippet:

int offset = 0;

void clear_screen() {
    unsigned char * video = 0xB8000;
    for(int i = 0; i < 2000; i =2){
        video[i] = ' ';
    }
}

void printc(char c) {
    unsigned char * video = 0xB8000;
    video[offset] = c;
    video[offset 1] = 0x03;
    offset  = 2;
}

void print(unsigned char *string) {
    char * sus = '\0';
    uint32 i = 0;
    printc('|');
    sus[0] = 'a';
    printc(sus[0]);  //this prints "a" correctly
    string[i] = 'c';
    while (string[i] != '\0') {
        printc(string[i]);   //this while loop is only called once 
        i  ;                 //it prints " " only once and exits
    }
    printc('|');
}

int bootup(void)
{
    clear_screen();

    // printc('h');
    // printc('e');
    // printc('l');                     /* These work */
    // printc('l');
    // printc('o');

    print("hello"); //this doesn't

    return 1;

}

Output that it prints:

|a |

Thanks in advance!!

edit

New print function

void print(unsigned char *string) {
    uint32 i = 0;
    printc('|');
    while (string[i] != '\0') {
        printc('i');  //not printed
        printc(string[i]);
        i  ;
    }
    printc('|');
}

still does not work

edit 2 updated the code as per @lundin's advice

int offset = 0;

void clear_screen() {
    unsigned char * video = (unsigned char *)0xB8000;
    for(int i = 0; i < 2000; i =2){
        video[i] = ' ';
    }
}

void printc(char c) {
    unsigned char * video = (unsigned char *)0xB8000;
    video[offset] = c;
    video[offset 1] = 0x03;
    offset  = 2;
}

void print(const char *string) {
    int i = 0;
    printc('|');
    while (string[i] != '\0') {
        printc('i');
        printc(string[i]);
        i  ;
    }
    printc('|');
}

int bootup(void)
{
    clear_screen();
    // printc('h');
    // printc('e');
    // printc('l');
    // printc('l');
    // printc('o');
    print("hello");
    return 1;

}

stack:

init_lm:
    mov ax, 0x10
    mov fs, ax          ;other segments are ignored
    mov gs, ax

    mov rbp, 0x90000    ;set up stack
    mov rsp, rbp

    ;Load kernel from disk
    xor ebx, ebx        ;upper 2 bytes above bh in ebx is for cylinder = 0x0
    mov bl, 0x2         ;read from 2nd sectors
    mov bh, 0x0         ;head
    mov ch, 1           ;read 1 sector
    mov rdi, KERNEL_ADDRESS
    call ata_chs_read


    jmp KERNEL_ADDRESS

    jmp $

CodePudding user response:

Your program has undefined behavior since it contains multiple lines that aren't valid C. You will have gotten compiler messages about those lines.

  • unsigned char * video = 0xB8000; etc is not valid C, you need an explicit cast. "Pointer from integer/integer from pointer without a cast" issues
  • Similarly, char * sus = '\0'; is also not valid C. You are trying to assign a pointer to a single character, which doesn't make sense. String handling beginner FAQ here: Common string handling pitfalls in C programming. It also addresses memory allocation basics.
  • sus[0] = 'a'; etc here you have wildly undefined behavior since sus isn't pointing at valid memory.
  • In case you are actually trying to access physical memory addresses, this isn't the correct way to do so. You need volatile qualified pointers. See How to access a hardware register from firmware? (In your case it probably isn't a register but everything from that link still applies - how to use hex constants etc.)
  • EDIT: void print(unsigned char *string) ... string[i] = 'c'; is also wrong. First of all you are passing a char* which is not necessarily compatible with unsigned char*. Then you shouldn't modify the passed string from inside a function called print, that doesn't make sense. This should have been const char* string to prevent such bugs. As it stands you are passing a string literal to this function and then try to modify it - that is undefined behavior since string literals are read-only.

Assuming gcc or clang, if you wish to block the compiler from generating an executable out of invalid C code, check out What compiler options are recommended for beginners learning C? In your case you also likely need the -ffreestanding option mentioned there.

CodePudding user response:

    char * sus = '\0';

Have not checked more... but this assigns a null pointer to sus, and most probably is not what you want to do.

  •  Tags:  
  • Related