Page 1 of 1

String literals not working

Posted: Fri Jan 29, 2021 1:48 am
by finlaymorrison
I am pretty new to OS dev, and I am trying to get some text to print out some text. It seems that if I pass a string to a function, it gets turned into nullchars, for example the code below:

```c
#include "../drivers/ports.h"
#include "../drivers/screen.h"

void print_first_char(char* str)
{
print_char(str[0], 0, 10, WHITE_ON_BLACK);
}

void kernel_main()
{
clear_screen();

char* str = "rewqtqrewqre";
print_char(str[0], 0, 10, WHITE_ON_BLACK);

print_first_char(str);
}
```

Will sucsessfuly print the 'r' character when the `print_first_char` function is commented out, however upon uncommenting it it no longer works,

I also found that looping through a string with a for loop does not work, in the following code, the top block works fine, and the bottom one does not.

```c
void kernel_main()
{
clear_screen();

char* str = "rewqtqrewqre";

print_char(str[0], 0, 10, WHITE_ON_BLACK);
print_char(str[1], 1, 10, WHITE_ON_BLACK);
print_char(str[2], 2, 10, WHITE_ON_BLACK);
print_char(str[3], 3, 10, WHITE_ON_BLACK);
print_char(str[4], 4, 10, WHITE_ON_BLACK);
print_char(str[5], 5, 10, WHITE_ON_BLACK);
}
```
and this code does not work:
```c
void kernel_main()
{
clear_screen();

char* str = "rewqtqrewqre";

for (int i = 0; i < 6; ++i)
{
print_char(str, i, 10, WHITE_ON_BLACK);
}
}
```

Any info for why this may not work would be greatly appreciated, if you would like to see more of the code my github repo is here: https://github.com/finlaymorrison/os

Re: String literals not working

Posted: Fri Jan 29, 2021 7:43 pm
by Octocontrabass
How many sectors is your kernel binary?

How many sectors does your bootloader load?

Re: String literals not working

Posted: Fri Jan 29, 2021 7:44 pm
by neon
Hi,

You are pushing 2 bytes for all ISRs yet popping 8 before IRET. Same error occurs with IRQ. Either do add esp, 2 or push dword instead of push byte. To ensure stack alignment, I recommend pushing dword. Farther if you are going to use STI, make sure the timer is enabled prior. I advise disabling it for now (CLI or just remove the STI's from the code.) Also need to emphasize not to copy and paste code unless you know precisely what it does.

Code: Select all

isr0:
    cli
    push byte 0
    push byte 0      <--
    jmp isr_common_stub

isr_common_stub:
    pusha

    mov ax, ds
    push eax
    mov ax, 0x10
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax

    call isr_handler

    pop eax
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    popa

    add esp, 8    <--
    sti     <--
    iret

Re: String literals not working

Posted: Fri Jan 29, 2021 8:24 pm
by Octocontrabass
neon wrote:You are pushing 2 bytes for all ISRs yet popping 8 before IRET.
PUSH doesn't support byte operands. In this case, NASM will treat the "byte" keyword as an optimization hint instead of the operand size.

I recommend deleting the "byte" keyword and relying on NASM's optimizer to choose the smallest instruction encoding. There's no need to specify the operand size, since it's already dword by default.

Re: String literals not working

Posted: Fri Jan 29, 2021 8:56 pm
by neon
Hi,

I believe you are right -- I was confusing instruction length without considering the CPU zero or sign extending the operand so this might be alright. The instruction itself supports imm8 -- 6a[imm8] -- but it appears to sign extend it to the operating mode size prior to pushing to the stack.