OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Jun 20, 2019 1:08 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 19 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Printing text with a C kernel doesn't work properly
PostPosted: Sun Feb 03, 2019 10:12 am 
Offline

Joined: Sun Feb 03, 2019 9:47 am
Posts: 9
Hello. I am trying to print some text with my bootloader and my kernel written in C (loaded at 0x7e00) but it doesn't print the whole text. However, if I declare the following char* and fill it with some text and print all the characters inside it one by one, it works but it's not very practical:
Code:
char* message = (char*)0x80000;

It makes me think it's a memory related issue and I am unsure how I can fix it. I read a post on reddit made by a person with the same problem as me and one of the replies said the .text section is fully loaded:
Quote:
If it’s getting through any one of the function calls correctly, then .text is probably fully loaded, at least. Is the entire string there? Try pooping the second-to-last byte out into Bochs’ debug port before writing, and see if it matches the character it should. Idunno how it’s arranged pre-load, but .rodata usually comes after .text so that and .data would be the last things to load. You’re (oddly) not using .data to preinitialize your VGA stuff (all those init values are compile-time-constant), so you’ve lost one potential canary there. I’d also put a magic value within your image at the very end, and have the loader place one just after it. Then you can check that both sync up with what they should be, = you’re reasonably sure your entire kernel has loaded.


Here is my source code:
https://hastebin.com/ehogozibuc.cpp Kernel's main file
https://hastebin.com/emuhexaqob.cpp video.c (functions to play with video memory)
https://hastebin.com/tacavorolu.sql Bootloader
https://hastebin.com/fudowoyude Linker script

Any thoughts or suggestions? Sorry if this is a noobish question, I just started learning this kind of thing. Thanks in advance :)


Top
 Profile  
 
 Post subject: Re: Printing text with a C kernel doesn't work properly
PostPosted: Sun Feb 03, 2019 10:54 am 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 421
Are you reading enough sectors to cover your entire kernel (including data)? I haven't actually looked at your code, but that is my first thought.


Last edited by MichaelPetch on Sun Feb 03, 2019 10:59 am, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: Printing text with a C kernel doesn't work properly
PostPosted: Sun Feb 03, 2019 10:57 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 3369
Location: Chichester, UK
You've written your bootloader with SQL?

(I haven't download your source files as I don't click on random links - you'd do better to store your source code in GitHub, or something similar.)


Top
 Profile  
 
 Post subject: Re: Printing text with a C kernel doesn't work properly
PostPosted: Sun Feb 03, 2019 11:10 am 
Offline

Joined: Sun Feb 03, 2019 9:47 am
Posts: 9
iansjack wrote:
You've written your bootloader with SQL?

(I haven't download your source files as I don't click on random links - you'd do better to store your source code in GitHub, or something similar.)


No. It's just Hastebin thinking the assembly code is SQL.


Top
 Profile  
 
 Post subject: Re: Printing text with a C kernel doesn't work properly
PostPosted: Sun Feb 03, 2019 11:17 am 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 421
Your bootloader only reads 2 sectors from disk. That is a total of 1024 bytes. If your kernel code and data exceed 1024 bytes not all the data will be loaded in memory. I happened to see a comment in the code that a string 2000 bytes long didn't work:
Code:
// However, if I have a 2000 characters long string and
    // call print(myString, 0x4f); it doesn't print the entire thing.
You don't say how you build your code either. If you are using a 64-bit compiler make sure you compile as 32-bit code with -m32 (or use an i686/i386 cross compiler)


Last edited by MichaelPetch on Sun Feb 03, 2019 11:22 am, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: Printing text with a C kernel doesn't work properly
PostPosted: Sun Feb 03, 2019 11:19 am 
Offline

Joined: Sun Feb 03, 2019 9:47 am
Posts: 9
MichaelPetch wrote:
Your bootloader only reads 2 sectors from disk. That is a total of 1024 bytes. If your kernel code and data exceed 1024 bytes not all the data will be loaded in memory. I happened to see a comment in the code that a string 2000 bytes long didn't work:
Code:
// However, if I have a 2000 characters long string and
    // call print(myString, 0x4f); it doesn't print the entire thing.

I changed AL to 0x04 so it reads 4 sectors and it did print more stuff but didn't print the whole string. I tried to go with 0x05 and it also worked. Then with 0x06 but any value greater than 0x05 bricks the code and nothing is printed.


Top
 Profile  
 
 Post subject: Re: Printing text with a C kernel doesn't work properly
PostPosted: Sun Feb 03, 2019 11:26 am 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 421
Since you read data into memory from disk and you don't know where the stack is that the BIOS set you should be setting SS:SP to something that won't be clobbered by the disk reads prior to using the int 13h/ah=2 BIOS function. SS=0x0000 and SP=0x7c00 would be fine given the stack will grow down from below where the bootloader is in memory.


Top
 Profile  
 
 Post subject: Re: Printing text with a C kernel doesn't work properly
PostPosted: Sun Feb 03, 2019 11:29 am 
Offline

Joined: Sun Feb 03, 2019 9:47 am
Posts: 9
MichaelPetch wrote:
Since you read data into memory from disk and you don't know where the stack is that the BIOS set you should be setting SS:SP to something that won't be clobbered by the disk reads prior to using the int 13h/ah=2 BIOS function. SS=0x0000 and SP=0x7c00 would be fine given the stack will grow down from below where the bootloader is in memory.

Isn't this enough?
Code:
mov ebp, 0x90000   
mov esp, ebp

This is executed after int 13h/ah=2.
I also tried this before int13h:
Code:
xor ax, ax
mov ss, ax
mov sp, 0x7c00 ; I'm probably not doing this right.


Top
 Profile  
 
 Post subject: Re: Printing text with a C kernel doesn't work properly
PostPosted: Sun Feb 03, 2019 11:33 am 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 1547
How big is your kernel, anyway? Randomly changing the number of sectors you load is pointless if you don't know how many you really need.

Your bootloader doesn't set up the stack before it starts using the BIOS interrupts. Remember, those need the stack too. If the stack overlaps the memory you're loading your kernel into, bad things will happen.

Your linker script is awfully small. You may be missing one or more sections that are required for your code to run correctly. The lack of .bss is particularly glaring - you can't guarantee uninitialized RAM will be set to zero, you need to initialize it yourself somehow, and including it in your binary is the simplest way.

I notice you didn't provide any of your build scripts. How are you building your kernel? A cross-compiler is strongly recommended.


Top
 Profile  
 
 Post subject: Re: Printing text with a C kernel doesn't work properly
PostPosted: Sun Feb 03, 2019 11:34 am 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 421
To make sure you don't clobber the stack during disk reads (which can cause the entire BIOS interrupt to fail or never return to your code) you must set a real mode stack before you do the disk read. There is nothing wrong with setting the protected mode stack after, but that doesn't help deal with the issue of the real mode stack needing to be set to something out of the way before doing a disk read. But yes, doing this before the disk read is fine:
Code:
xor ax, ax
mov ss, ax
mov sp, 0x7c00 ; I'm probably not doing this right.
It would also help to know what command lines you use to compile, assemble, and link all your code together as that can also cause problems if done improperly.


Top
 Profile  
 
 Post subject: Re: Printing text with a C kernel doesn't work properly
PostPosted: Sun Feb 03, 2019 11:38 am 
Offline

Joined: Sun Feb 03, 2019 9:47 am
Posts: 9
Here is the build script (I'm using Parrot OS (linux) x64):
Code:
# clear
rm *.bin *.img *.o

# compile
nasm boot.asm -f bin -o boot.bin
gcc -m32 -ffreestanding -c main.c -o main.o
gcc -m32 -static -nostartfiles -c video.c -o video.o

# link
ld -melf_i386 -N -T link.ld -o kernel.o main.o video.o
objcopy -R .note -R .comment -S -O binary kernel.o kernel.bin

boot_sz=$(stat -c %s boot.bin)
kernel_sz=$(stat -c %s kernel.bin)
sum_sz=$(($boot_sz + $kernel_sz))
dummy_sz=$(./dummy_size.py $sum_sz)
head -c $dummy_sz < /dev/zero > tmp

cat boot.bin kernel.bin tmp > kernel.img
#cat
rm tmp
rm *.o


Top
 Profile  
 
 Post subject: Re: Printing text with a C kernel doesn't work properly
PostPosted: Sun Feb 03, 2019 11:42 am 
Offline

Joined: Sun Feb 03, 2019 9:47 am
Posts: 9
Octocontrabass wrote:
How big is your kernel, anyway? Randomly changing the number of sectors you load is pointless if you don't know how many you really need.

Your bootloader doesn't set up the stack before it starts using the BIOS interrupts. Remember, those need the stack too. If the stack overlaps the memory you're loading your kernel into, bad things will happen.

Your linker script is awfully small. You may be missing one or more sections that are required for your code to run correctly. The lack of .bss is particularly glaring - you can't guarantee uninitialized RAM will be set to zero, you need to initialize it yourself somehow, and including it in your binary is the simplest way.

I notice you didn't provide any of your build scripts. How are you building your kernel? A cross-compiler is strongly recommended.

The final size of kernel.bin is 2248 bytes and I tried this before using interrupts:
Code:
xor ax, ax
mov ss, ax
mov sp, 0x7c00


Top
 Profile  
 
 Post subject: Re: Printing text with a C kernel doesn't work properly
PostPosted: Sun Feb 03, 2019 11:44 am 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 421
Houston we have a problem:
Code:
gcc -m32 -ffreestanding -c main.c -o main.o
gcc -m32 -static -nostartfiles -c video.c -o video.o

# link
ld -melf_i386 -N -T link.ld -o kernel.o main.o video.o
objcopy -R .note -R .comment -S -O binary kernel.o kernel.bin
First off you aren't using a cross compiler so you may have potential issues with position independent code. You can compile each C file with -fno-PIC. You'd normally use the -fno-PIE when using GCC to link to an executable.This leads to the big glaring problem.You are generating the binary from the .o(object file).You are not linking your code into an executable and then converting the executable to a binary file.


Top
 Profile  
 
 Post subject: Re: Printing text with a C kernel doesn't work properly
PostPosted: Sun Feb 03, 2019 11:49 am 
Offline

Joined: Sun Feb 03, 2019 9:47 am
Posts: 9
MichaelPetch wrote:
Houston we have a problem:
Code:
gcc -m32 -ffreestanding -c main.c -o main.o
gcc -m32 -static -nostartfiles -c video.c -o video.o

# link
ld -melf_i386 -N -T link.ld -o kernel.o main.o video.o
objcopy -R .note -R .comment -S -O binary kernel.o kernel.bin
First off you aren't using a cross compiler so you may have potential issues with position independent code. You can compile each C file with -fno-PIC. You'd normally use the -fno-PIE when using GCC to link to an executable.This leads to the big glaring problem.You are generating the binary from the .o(object file).You are not linking your code into an executable and then converting the executable to a binary file.

So should I do
Code:
gcc -fno-PIC -m32 -ffreestanding -c main.c -o main.o
gcc -fno-PIC -m32 -static -nostartfiles -c video.c -o video.o

instead?


Top
 Profile  
 
 Post subject: Re: Printing text with a C kernel doesn't work properly
PostPosted: Sun Feb 03, 2019 11:54 am 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 421
I'd clean it up and do it this way:
Code:
#!/bin/bash

nasm -f bin boot.asm -o boot.bin
gcc -m32 -c -ffreestanding -fno-PIC main.c -o main.o
gcc -m32 -c -ffreestanding -fno-PIC video.c -o video.o

# Link files to kernel.elf using GCC rather than LD
gcc -m32 -Tlink.ld -fno-PIE -nostartfiles main.o video.o -o kernel.elf

objcopy -R .note -R .comment -S -O binary kernel.elf kernel.bin

# Make disk image size of 1.44MiB floppy
dd if=/dev/zero of=disk.img bs=1024 count=1440

dd if=boot.bin of=disk.img conv=notrunc
dd if=kernel.bin of=disk.img seek=1 conv=notrunc
This should compile each individual file, link them to an executable called kernel.elf and that executable is converted into a binary file call kernel.bin. I also simplify creating a disk image (I chose a nominal floppy disk size of 1.44MiB). Bootloader in first sector and kernel starting in second sector.
As was mentioned to you by the other commenter you rely on the BSS section of memory already being zero. You may be lucky that is the case but it isn't guaranteed and could cause you problems later on.


Last edited by MichaelPetch on Sun Feb 03, 2019 12:24 pm, edited 2 times in total.

Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 19 posts ]  Go to page 1, 2  Next

All times are UTC - 6 hours


Who is online

Users browsing this forum: No registered users and 8 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group