different result running same command in function and on main – x86-64 toy_kernel

I’m writing my own kernel (32-bit for now) and command works if I run on main but when running on different function it behaves differently. Any idea how and why? EDIT: the problem lies in non-functioning dereference of pointers inside other functions.

int foo(const char *str)
{   
    *(char*)0xb8000 = *str; // clears the screen probably because of 0 padding at the end
}
extern void main() {
    const char str[4] = {'A', 'B', 'C', '\0'};
     *(char*)0xb8000 = *str; // works good
    for(int i=0;i<1000000000;i++); // for delay
    foo(str);
    for(;;);
    return;
}

I expected it to behave the same but it didn’t

booting code is here

[org 0x7c00]
KERNEL_LOCATION equ 0x1000

mov [boot_disk], dl

; set up stack
xor ax, ax                          
mov es, ax
mov ds, ax
mov bp, 0x8000
mov sp, bp


// GDT loading to memory and other stuff


[bits 32]
start_protected_mode:
    mov ax, DATA_SEG
    mov ds, ax
    mov ss, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    
    mov ebp, 0x90000        ; 32 bit stack base pointer
    mov esp, ebp

    jmp KERNEL_LOCATION


times 510-($-$$) db 0
dw 0xaa55

makefile

all:
x86_64-elf-gcc -Wall -nostdlib -ffreestanding -m64 -g -c "kernel.c" -o "kernel.o"
x86_64-elf-gcc -Wall -nostdlib -ffreestanding -m64 -g -c "idt.c" -o "idt.o"
x86_64-elf-gcc -Wall -nostdlib -ffreestanding -m64 -g -c "system.c" -o "system.o"
nasm "kernel_enrty.asm" -f elf64 -o "kernel_entry.o"
nasm "start.asm" -f elf64 -o "start.o"
x86_64-elf-ld -nostdlib -o "full_kernel.bin" -Ttext 0x1000 "kernel_entry.o" "start.o" "idt.o" "system.o"  "kernel.o" -j .text --oformat binary
nasm "boot.asm" -f bin -o "boot.bin"
cat "boot.bin" "full_kernel.bin" > "everything.bin"
nasm "padding.asm" -f bin -o "padding.bin"
cat "everything.bin" "padding.bin" > "OS.bin"

  • no sadly it does not

    – 

  • 1

    Try expanding on what “works good” means. I don’t think we can try your code ourselves, so we have to go from your description. My point was whatever the construct in main does, passing str into a function will lose the size information so the function definitely copies only one char.

    – 




  • 1

    for(int i=0;i<1000000000;i++); is a no-op btw, it doesn’t do jack and will just get discarded by the compiler. Declare i as volatile if you want it to do something.

    – 

  • 1

    There is no reason why both assignments should behave different. Unless you have a messed up setup where parameter passing does not work properly, they will both assign 'A' to address 0xb8000. Is your stack configured correctly? You might add a few details how you build that kernel and how you run it.

    – 




  • 1

    Time to go through the corresponding assembler code?

    – 




Leave a Comment