[Solved] Cannot use multiple function calls in my C kernel.

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
psimonson1988
Member
Member
Posts: 40
Joined: Tue Jul 16, 2019 8:40 pm

[Solved] Cannot use multiple function calls in my C kernel.

Post by psimonson1988 »

What am I doing wrong? Everything else works print a character at a time, clearing the screen and initializing the terminal.

But every time I execute:

Code: Select all

print("Some text");
NOTE: Currently I removed the print function from the kernel main, so it doesn't call that function right now.

But if you add it back in then it does the following.
It doesn't work, it's like it skips that function for some reason.
Below should be all code that is related to the issue.

stage2.asm:

Code: Select all

; stage 2 boot loader.
; by Philip Simonson.
; =======================

[org 0x7e00]
[bits 16]

start:
	mov [iBootDrive], dl

	; set text mode (80x25)
	mov ax, 0x0003
	int 0x10

	call a20_bios
	call check_a20

	mov si, op_loading
	call print

	call reset_disk

	mov ax, 2   ; this is the starting sector LBA addressing
	mov cx, 9  ; set this to count of sectors to read
	mov bx, load_segment
	mov es, bx
	mov bx, load_offset
	call read_disk

	; switch on protected mode
	cli
	lgdt [gdt.pointer]
	mov eax, cr0
	or eax, 1
	mov cr0, eax

	jmp dword 0x08:INIT_PM

%include "common.inc"
%include "disk.inc"
%include "a20.inc"
%include "gdt.inc"

[bits 32]

INIT_PM:
	mov ax, 0x10
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	mov ss, ax
	mov ebp, 0x90000
	mov esp, ebp

	call run_offset
	hlt

%include "common32.inc"

op_loading db "Loading kernel, please wait",0
op_done db "done!",10,13,0
op_a20yes db "A20 is enabled.",10,13,0
op_a20no db "A20 is disabled.",10,13,0
op_progress db 0x2e,0
op_failed db 10,13,"File not found!",10,13,0
load_segment equ 0x1000
load_offset equ 0x0000
run_offset equ 0x00010000

%include "bs.inc"
entry.asm:

Code: Select all

; entry point for kernel

[bits 32]

section .text

extern kernel_main

global _start
_start:
	call kernel_main
	hlt
io.c:

Code: Select all

/*
 * Author: Philip R. Simonson
 * Date  : 07/01/2020
 *
 ****************************************************************
 */

#include "vga.h"

/* Print a string on screen at given (x,y) position.
 */
void print_at(int col, int row, char *s)
{
	int offset, i;

	if(col >= MAX_COLS || row >= MAX_ROWS) {
		offset = print_char(0, 0, 'E');
		set_cursor_offset(offset);
	}

	i = 0;
	while(s[i] != 0) {
		offset = print_char(col, row, s[i]);
		/* Compute row/col for next iteration */
		col = get_offset_row(offset);
		row = get_offset_col(offset);
	}
}
/* Print a string on screen at current location.
 */
void print(char *s)
{
	print_at(-1, -1, s);
}
kernel.c:

Code: Select all

#include "vga.h"
#include "io.h"

void kernel_main(void)
{
	term_init(BLUE, YELLOW);
	print_char(-1, -1, 'H');
	print_char(-1, -1, 'e');
	print_char(-1, -1, 'l');
	print_char(-1, -1, 'l');
	print_char(-1, -1, 'o');
	print_char(-1, -1, ' ');
	print_char(-1, -1, 'W');
	print_char(-1, -1, 'o');
	print_char(-1, -1, 'r');
	print_char(-1, -1, 'l');
	print_char(-1, -1, 'd');
	print_char(-1, -1, '!');
	print_char(-1, -1, '\n');
}
link.ld:

Code: Select all

ENTRY(kernel_main);
OUTPUT_FORMAT(elf32-i386);
OUTPUT_ARCH(i386:i386);
BASE_ADDR = 0x00010000;

SECTIONS
{
	.text BASE_ADDR : AT(BASE_ADDR)
	{
		code = .;
		*(.text)
		. = ALIGN(4K);
	}
	.rodata : AT(BASE_ADDR + (rodata - code))
	{
		rodata = .;
		*(.rodata)
		. = ALIGN(4K);
	}
	.data : AT(BASE_ADDR + (data - code))
	{
		data = .;
		*(.data)
		. = ALIGN(4K);
	}
	.bss : AT(BASE_ADDR + (bss - code))
	{
		bss = .;
		*(.bss)
		*(COMMON)
		. = ALIGN(4K);
	}
	/DISCARD/ :
	{
		*(.comment);
		*(.igot.*);
		*(.eh_frame);
	}
}
NOTE: I might not have everything needed here, so I'm posting the github project for you to look at.

The code for this project: github.com - boot32-barebones

Thanks in advance for any and all information to correct this issue with my print and print_at functions. Why they (print string functions) don't work was the question? I've been mucking around with this every since Michael Petch and others helped with my last issue. Basically what I'm going for with this project is a starting point for beginners, one that has every tricky 16 bit and 32 bit mode stuff already done. That way all a beginner has to do is clone this project and start making the kernel. If they're going for a 32-bit operating system.

- Phil
Last edited by psimonson1988 on Wed Jul 01, 2020 10:41 pm, edited 1 time in total.
nexos
Member
Member
Posts: 1081
Joined: Tue Feb 18, 2020 3:29 pm
Libera.chat IRC: nexos

Re: Cannot use multiple function calls in my C kernel.

Post by nexos »

What happens when you execute the print function?
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg
Octocontrabass
Member
Member
Posts: 5574
Joined: Mon Mar 25, 2013 7:01 pm

Re: Cannot use multiple function calls in my C kernel.

Post by Octocontrabass »

I've said before that most operating system tutorials are written by authors who are not familiar enough with the subject matter to notice that they're writing bad code or giving bad advice.

Any particular reason you chose to write your own bootloader instead of using an existing one like GRUB? It does a lot of the hard work for you.

Why aren't you using a cross-compiler?

Did you run it under a debugger to see where things break down?

Are the strings even in your kernel binary?
psimonson1988
Member
Member
Posts: 40
Joined: Tue Jul 16, 2019 8:40 pm

Re: Cannot use multiple function calls in my C kernel.

Post by psimonson1988 »

nexos wrote:What happens when you execute the print function?
It doesn't print anything, like I said it's almost like the print function is skip altogether.
Octocontrabass wrote:Any particular reason you chose to write your own bootloader instead of using an existing one like GRUB? It does a lot of the hard work for you.
That is why I'm asking here for your guys help in writing a solid two stage boot loader with a basic kernel "the right way, not the wrong way". The boot loader is done right now, both stages. Unless, in stage2.asm and link.ld I'm incorrectly loading the kernel?
Octocontrabass wrote:Did you run it under a debugger to see where things break down?
It does NOT break down at all it will print character by character and fill the screen no problems there. It's only a problem with strings.
Octocontrabass wrote:Are the strings even in your kernel binary?
Not sure I haven't checked if the strings are in the binary but, now I will and report back.

EDIT: Below is the hexdump -C kernel.bin - To answer your question the strings aren't inside the binary.

hexdump -C kernel.bin:

Code: Select all

00000000  e8 01 00 00 00 f4 f3 0f  1e fb 83 ec 14 6a 0e 6a  |.............j.j|
00000010  01 e8 99 03 00 00 83 c4  0c 6a 48 6a ff 6a ff e8  |.........jHj.j..|
00000020  9b 02 00 00 83 c4 0c 6a  65 6a ff 6a ff e8 8d 02  |.......jej.j....|
00000030  00 00 83 c4 0c 6a 6c 6a  ff 6a ff e8 7f 02 00 00  |.....jlj.j......|
00000040  83 c4 0c 6a 6c 6a ff 6a  ff e8 71 02 00 00 83 c4  |...jlj.j..q.....|
00000050  0c 6a 6f 6a ff 6a ff e8  63 02 00 00 83 c4 0c 6a  |.joj.j..c......j|
00000060  20 6a ff 6a ff e8 55 02  00 00 83 c4 0c 6a 57 6a  | j.j..U......jWj|
00000070  ff 6a ff e8 47 02 00 00  83 c4 0c 6a 6f 6a ff 6a  |.j..G......joj.j|
00000080  ff e8 39 02 00 00 83 c4  0c 6a 72 6a ff 6a ff e8  |..9......jrj.j..|
00000090  2b 02 00 00 83 c4 0c 6a  6c 6a ff 6a ff e8 1d 02  |+......jlj.j....|
000000a0  00 00 83 c4 0c 6a 64 6a  ff 6a ff e8 0f 02 00 00  |.....jdj.j......|
000000b0  83 c4 0c 6a 21 6a ff 6a  ff e8 01 02 00 00 83 c4  |...j!j.j........|
000000c0  0c 6a 0a 6a ff 6a ff e8  f3 01 00 00 83 c4 1c c3  |.j.j.j..........|
000000d0  f3 0f 1e fb 57 56 53 8b  5c 24 10 8b 74 24 14 8b  |....WVS.\$..t$..|
000000e0  7c 24 18 83 fb 4f 7f 3e  83 fe 18 7f 39 0f b6 07  ||$...O.>....9...|
000000f0  84 c0 74 2e 83 ec 04 0f  be c0 50 56 53 e8 bd 01  |..t.......PVS...|
00000100  00 00 89 c6 89 04 24 e8  94 00 00 00 89 c3 89 34  |......$........4|
00000110  24 e8 a6 00 00 00 89 c6  0f b6 07 83 c4 10 84 c0  |$...............|
00000120  75 d2 5b 5e 5f c3 83 ec  04 6a 45 6a 00 6a 00 e8  |u.[^_....jEj.j..|
00000130  8b 01 00 00 89 04 24 e8  fc 00 00 00 83 c4 10 eb  |......$.........|
00000140  ac f3 0f 1e fb 83 ec 10  ff 74 24 14 6a ff 6a ff  |.........t$.j.j.|
00000150  e8 7b ff ff ff 83 c4 1c  c3 f3 0f 1e fb 8b 54 24  |.{............T$|
00000160  04 ec c3 f3 0f 1e fb 8b  54 24 04 8b 44 24 08 ee  |........T$..D$..|
00000170  c3 f3 0f 1e fb 8b 54 24  04 66 ed c3 f3 0f 1e fb  |......T$.f......|
00000180  8b 54 24 04 8b 44 24 08  66 ef c3 f3 0f 1e fb 8b  |.T$..D$.f.......|
00000190  44 24 08 8d 04 80 c1 e0  04 03 44 24 04 01 c0 c3  |D$........D$....|
000001a0  f3 0f 1e fb 8b 4c 24 04  ba 67 66 66 66 89 c8 f7  |.....L$..gfff...|
000001b0  ea c1 fa 06 c1 f9 1f 89  d0 29 c8 c3 f3 0f 1e fb  |.........)......|
000001c0  8b 4c 24 04 ba 67 66 66  66 89 c8 f7 ea c1 fa 06  |.L$..gfff.......|
000001d0  89 c8 c1 f8 1f 29 c2 69  c2 60 ff ff ff 01 c8 89  |.....).i.`......|
000001e0  c2 c1 ea 1f 01 d0 d1 f8  c3 f3 0f 1e fb 53 83 ec  |.............S..|
000001f0  10 6a 0e 68 d4 03 00 00  e8 66 ff ff ff c7 04 24  |.j.h.....f.....$|
00000200  d5 03 00 00 e8 50 ff ff  ff 0f b6 c0 c1 e0 08 89  |.....P..........|
00000210  c3 83 c4 08 6a 0f 68 d4  03 00 00 e8 43 ff ff ff  |....j.h.....C...|
00000220  c7 04 24 d5 03 00 00 e8  2d ff ff ff 0f b6 c0 01  |..$.....-.......|
00000230  d8 01 c0 83 c4 18 5b c3  f3 0f 1e fb 56 53 83 ec  |......[.....VS..|
00000240  0c 8b 44 24 18 89 c3 c1  eb 1f 01 c3 89 de d1 fe  |..D$............|
00000250  6a 0e 68 d4 03 00 00 e8  07 ff ff ff 83 c4 08 c1  |j.h.............|
00000260  fb 09 0f b6 db 53 68 d5  03 00 00 e8 f3 fe ff ff  |.....Sh.........|
00000270  83 c4 08 6a 0f 68 d4 03  00 00 e8 e4 fe ff ff 83  |...j.h..........|
00000280  c4 08 89 f0 0f b6 f0 56  68 d5 03 00 00 e8 d1 fe  |.......Vh.......|
00000290  ff ff 83 c4 14 5b 5e c3  f3 0f 1e fb 0f b6 44 24  |.....[^.......D$|
000002a0  04 c1 e0 04 0a 44 24 08  c3 f3 0f 1e fb 0f b6 44  |.....D$........D|
000002b0  24 04 c1 e0 04 0a 44 24  08 a2 01 20 01 00 c3 f3  |$.....D$... ....|
000002c0  0f 1e fb 53 83 ec 08 8b  44 24 10 8b 54 24 14 8b  |...S....D$..T$..|
000002d0  5c 24 18 85 c0 78 3e 85  d2 78 3a 8d 0c 92 c1 e1  |\$...x>..x:.....|
000002e0  04 01 c1 01 c9 80 fb 0a  74 34 a1 04 20 01 00 88  |........t4.. ...|
000002f0  1c 08 a1 04 20 01 00 0f  b6 15 01 20 01 00 88 54  |.... ...... ...T|
00000300  08 01 8d 59 02 83 ec 0c  53 e8 2a ff ff ff 89 d8  |...Y....S.*.....|
00000310  83 c4 18 5b c3 e8 cf fe  ff ff 89 c1 eb c7 ba 67  |...[...........g|
00000320  66 66 66 89 c8 f7 ea c1  fa 06 c1 f9 1f 29 ca 8d  |fff..........)..|
00000330  4c 92 05 89 cb c1 e3 05  eb cb f3 0f 1e fb 80 3d  |L..............=|
00000340  00 20 01 00 00 74 67 55  57 56 53 83 ec 0c bd 50  |. ...tgUWVS....P|
00000350  00 00 00 bb 00 00 00 00  b8 00 00 00 00 bf 67 66  |..............gf|
00000360  66 66 eb 05 83 ed 01 74  33 be 19 00 00 00 83 ec  |ff.....t3.......|
00000370  04 6a 20 53 50 e8 45 ff  ff ff 89 c1 f7 ef c1 fa  |.j SP.E.........|
00000380  06 89 c8 c1 f8 1f 89 d3  29 c3 89 0c 24 e8 2a fe  |........)...$.*.|
00000390  ff ff 83 c4 10 83 ee 01  75 d4 eb c8 83 ec 0c 6a  |........u......j|
000003a0  00 e8 92 fe ff ff 83 c4  1c 5b 5e 5f 5d c3 c3 f3  |.........[^_]...|
000003b0  0f 1e fb 83 ec 0c 8b 44  24 10 8b 54 24 14 80 3d  |.......D$..T$..=|
000003c0  00 20 01 00 00 74 04 83  c4 0c c3 c6 05 00 20 01  |. ...t........ .|
000003d0  00 01 c7 05 04 20 01 00  00 80 0b 00 c1 e0 04 09  |..... ..........|
000003e0  d0 a2 01 20 01 00 e8 4f  ff ff ff eb da 66 90 66  |... ...O.....f.f|
000003f0  90 66 90 66 90 66 90 66  90 66 90 66 90 66 90 66  |.f.f.f.f.f.f.f.f|
*
00000ff0  90 66 90 66 90 66 90 66  90 66 90 66 90 66 90 90  |.f.f.f.f.f.f.f..|
00001000  04 00 00 00 0c 00 00 00  05 00 00 00 47 4e 55 00  |............GNU.|
00001010  02 00 00 c0 04 00 00 00  03 00 00 00 04 00 00 00  |................|
00001020  0c 00 00 00 05 00 00 00  47 4e 55 00 02 00 00 c0  |........GNU.....|
00001030  04 00 00 00 03 00 00 00  04 00 00 00 0c 00 00 00  |................|
00001040  05 00 00 00 47 4e 55 00  02 00 00 c0 04 00 00 00  |....GNU.........|
00001050  03 00 00 00 04 00 00 00  0c 00 00 00 05 00 00 00  |................|
00001060  47 4e 55 00 02 00 00 c0  04 00 00 00 03 00 00 00  |GNU.............|
00001070
Now my question is what is wrong with the linker script: link.ld.. that is why the right data and what not isn't in the binary is it?
nullplan
Member
Member
Posts: 1791
Joined: Wed Aug 30, 2017 8:24 am

Re: Cannot use multiple function calls in my C kernel.

Post by nullplan »

The strings are in there. Although you did screw up the ELF headers. Attached is a series of patches I made that fixes some of your issues (with detailed explanations in the commit messages). You should be able to apply them with "git am".

Your main problem, however, is that you don't load enough sectors. You don't even load your entire vanilla kernel (which takes up 4096 bytes on disk), because in your stage 1, you always set CX to 2, so you only ever load 2 sectors (1024 bytes). Now, currently you only need 4096 bytes, because you have no .data, and .bss does not need to be part of the binary (hey, @bzt, remember our recent conversation?). Although this also means that nothing is clearing BSS to zero, so you might want to add that post haste. But, as soon as you add any .data, you are going to need more than 4096 bytes. So you will need to adjust the boot loader to however long your kernel really is. Or else, you will need to make your bootloader recognize the file size, which is going to be hard in a raw binary.

I would counsel against using the kernel.elf as it is now, because for some odd reason, the alignment on the first LOAD segment was set to 2MB, so none of your sections are far enough apart to create a second LOAD segment. I would use the PHDRS linker script directive to fix that. And I would also strongly counsel for the use of a cross compiler. I have an i686-elf-gcc lying around for just such a thing. Compiling Binutils and GCC with no libc is really easy.

EDIT: Yes, there is no string in the vanilla kernel from github. That's because you deleted it in kernel.c.
Attachments
patchset.tar.gz
Patch set
(2.22 KiB) Downloaded 18 times
Carpe diem!
User avatar
bzt
Member
Member
Posts: 1584
Joined: Thu Oct 13, 2016 4:55 pm
Contact:

Re: Cannot use multiple function calls in my C kernel.

Post by bzt »

nullplan wrote:I would counsel against using the kernel.elf as it is now, because for some odd reason, the alignment on the first LOAD segment was set to 2MB
I've solved this one some time ago. The linker flags "-n" (or was it "-N"?) and "-z max-page-size=16" will remove that 2M alignment constraint. Undocumented (sort of), but guaranteed to work.

Cheers,
bzt
psimonson1988
Member
Member
Posts: 40
Joined: Tue Jul 16, 2019 8:40 pm

Re: Cannot use multiple function calls in my C kernel.

Post by psimonson1988 »

Thanks for all of your advice, tips, and answers. They've all been a big help in this project and now it's almost complete, next up keyboard then it's done. That is as far as I will go with this because it is "barebones". In other words, just the basics to get beginners a starting point. Just fixed the print_at function now printing text properly. So all is well so far, everything that is currently implemented works now after applying your patches thanks a bunch for that. Marking this topic as solved.

Cheers,
Phil
Post Reply