Custom kernel not reading global variables and char*

1

I have a custom bootloader booting into a custom kernel. I'm writing in C now the assembly is out of the way.

So far, local variables and methods work fine, but global variables aren't being recognized when it's compiled and ran.

I have these three functions:

void SetChar(int VidIndex, char c) {    //Print a single char to a mem index set by VidIndex : WORKS!!
    char* vidPtr = (char*)0xb8000;
    vidPtr += VidIndex * 2;
    *vidPtr = c;
}

void PrintString(char* string) {        //Print 20 chars of a string, as a test :   NOT WORKS
    char* ptr = string;
    for (int t = 0; t < 20; t++) {
        SetChar(t, *ptr);
        ptr++;
    }
}

void ClearScreen() {                //Sets all chars in Video Memory to empty : WORKS!!

    for (char* ptr = (char*)0xb8000; ptr < (char*)(0xb8000 + 4000); ptr+=0x02) {
        *ptr = ' ';
    }
}

Using a main function such as this works fine and does what I want it to:

void _main() {
    
    ClearScreen();

    SetChar(5, 'H');
    SetChar(6, 'e');
    SetChar(7, 'l');
    SetChar(8, 'l');
    SetChar(9, 'o');

    return ;
}

Works fine

However, If I do this:

char* WelcomeString = "Welcome to my 32 bit OS with a C kernel.";

void _main() {
    
    ClearScreen();

    PrintString(WelcomeString);

    return ;
}

Then the image is completely black with nothing on it. Looking at the binary data reveals that the char* bytes aren't compiled in to it. This doesn't work with other global variables either. I am compiling and linking in a .bat like so:

nasm "C:\Users\Braiden\source\repos\Operating System\Bootloader.asm" -o bootloader.bin -f bin -i "C:\Users\Braiden\source\repos\Operating System"

nasm "C:\Users\Braiden\source\repos\Operating System\kernel_entry.asm" -f elf64 -o kernel_entry.o

nasm "C:\Users\Braiden\source\repos\Operating System\padding.asm" -o padding.bin -f bin

gcc -ffreestanding -c "C:\Users\Braiden\source\repos\Operating System\Kernel.c" -o kernel.o

ld -o kernel.tmp -Ttext 0x1000 kernel_entry.o kernel.o 
objcopy -O binary -j .text  kernel.tmp kernel.bin

copy /b bootloader.bin+kernel.bin+padding.bin os-image.img

pause

What could be the reason that it is acting this way? It is very strange to me. I'm willing to provide more information if needed. I'm just not sure what I need to provide.

Edit: Bootloader.asm

        global _start

_start:

[bits 16]
[org 0x7c00]

    KERNEL_ENTRY equ 0x1000
    mov bp, 0x8000
    mov sp, bp

    mov bx, welcomeString
    call print_func

    mov [ BOOT_DRIVE ], dl                  ; BIOS stores our boot drive in DL , so it ’s
                                            ; best to remember this for later.
    mov bp, 0x7c00                          ; Here we set our stack safely out of the
    mov sp, bp                              ; way , at 0 x8000
    mov bx, KERNEL_ENTRY                    ; Load 5 sectors to 0x0000 (es):KERNEL_ENTRY (bx)
    mov dh, 41                              ; from the boot disk.
    mov dl, [ BOOT_DRIVE ]
    call ReadDisk

    mov bx, readSuccessString               ; Print Success after reading disk
    call print_func

    mov bx, 0x7e00                          ; Let's see if we loaded the area
    call print_hex_func                     ; correctly
    call print_newline_func
    call PrintAddress

    call print_newline_func

    jmp switch_to_pm

    jmp $

%include "io.asm"
%include "print.asm"
%include "gdt.asm"

welcomeString:
    db 'Hello. Welcome to OS', 13, 10,0

readSuccessString:
    db 'Disk read Success', 13, 10, 0

switch_to_pm:
    cli

    lgdt [gdt_descriptor]
    mov eax, cr0
    or eax, 0x1
    mov cr0, eax

    jmp CODE_SEG:init_pm
    
[bits 32]

init_pm:

    mov ax, DATA_SEG
    mov ds, ax
    mov ss, ax
    mov es, ax
    mov fs, ax
    mov gs, ax

    mov ebp, 0x90000
    mov esp, ebp

    jmp BEGIN_PM

BEGIN_PM:

    jmp KERNEL_ENTRY    ; jump out of our 512 byte sector into the rest of our loaded memory
                        ; so we have much more space to work, and start the kernel
    jmp $

MSG_PM:
    db 'success', 0

times 510-($-$$) db 0

dw 0xaa55

kernel_entry.asm

[bits 32]
[extern _main]
call _main
jmp $

gcc -v output: (Using MinGW)

Using built-in specs.
COLLECT_GCC=C:\ProgramData\chocolatey\lib\mingw\tools\install\mingw64\bin\gcc.exe
Target: x86_64-w64-mingw32
Configured with: ../../../src/gcc-8.1.0/configure --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --target=x86_64-w64-mingw32 --prefix=/mingw64 --with-sysroot=/c/mingw810/x86_64-810-posix-seh-rt_v6-rev0/mingw64 --enable-shared --enable-static --disable-multilib --enable-languages=c,c++,fortran,lto --enable-libstdcxx-time=yes --enable-threads=posix --enable-libgomp --enable-libatomic --enable-lto --enable-graphite --enable-checking=release --enable-fully-dynamic-string --enable-version-specific-runtime-libs --disable-libstdcxx-pch --disable-libstdcxx-debug --enable-bootstrap --disable-rpath --disable-win32-registry --disable-nls --disable-werror --disable-symvers --with-gnu-as --with-gnu-ld --with-arch=nocona --with-tune=core2 --with-libiconv --with-system-zlib --with-gmp=/c/mingw810/prerequisites/x86_64-w64-mingw32-static --with-mpfr=/c/mingw810/prerequisites/x86_64-w64-mingw32-static --with-mpc=/c/mingw810/prerequisites/x86_64-w64-mingw32-static --with-isl=/c/mingw810/prerequisites/x86_64-w64-mingw32-static --with-pkgversion='x86_64-posix-seh-rev0, Built by MinGW-W64 project' --with-bugurl=https://sourceforge.net/projects/mingw-w64 CFLAGS='-O2 -pipe -fno-ident -I/c/mingw810/x86_64-810-posix-seh-rt_v6-rev0/mingw64/opt/include -I/c/mingw810/prerequisites/x86_64-zlib-static/include -I/c/mingw810/prerequisites/x86_64-w64-mingw32-static/include' CXXFLAGS='-O2 -pipe -fno-ident -I/c/mingw810/x86_64-810-posix-seh-rt_v6-rev0/mingw64/opt/include -I/c/mingw810/prerequisites/x86_64-zlib-static/include -I/c/mingw810/prerequisites/x86_64-w64-mingw32-static/include' CPPFLAGS=' -I/c/mingw810/x86_64-810-posix-seh-rt_v6-rev0/mingw64/opt/include -I/c/mingw810/prerequisites/x86_64-zlib-static/include -I/c/mingw810/prerequisites/x86_64-w64-mingw32-static/include' LDFLAGS='-pipe -fno-ident -L/c/mingw810/x86_64-810-posix-seh-rt_v6-rev0/mingw64/opt/lib -L/c/mingw810/prerequisites/x86_64-zlib-static/lib -L/c/mingw810/prerequisites/x86_64-w64-mingw32-static/lib '
Thread model: posix
gcc version 8.1.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project)
COLLECT_GCC_OPTIONS='-v' '-ffreestanding' '-c' '-o' 'kernel.o' '-mtune=core2' '-march=nocona'
 C:/ProgramData/chocolatey/lib/mingw/tools/install/mingw64/bin/../libexec/gcc/x86_64-w64-mingw32/8.1.0/cc1.exe -quiet -v -iprefix C:/ProgramData/chocolatey/lib/mingw/tools/install/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/ -D_REENTRANT C:\Users\Braiden\source\repos\Operating System\Kernel.c -quiet -dumpbase Kernel.c -mtune=core2 -march=nocona -auxbase-strip kernel.o -version -ffreestanding -o C:\Users\Braiden\AppData\Local\Temp\ccTxrZFP.s
GNU C17 (x86_64-posix-seh-rev0, Built by MinGW-W64 project) version 8.1.0 (x86_64-w64-mingw32)
        compiled by GNU C version 8.1.0, GMP version 6.1.2, MPFR version 4.0.1, MPC version 1.1.0, isl version isl-0.18-GMP

GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
ignoring duplicate directory "C:/ProgramData/chocolatey/lib/mingw/tools/install/mingw64/lib/gcc/../../lib/gcc/x86_64-w64-mingw32/8.1.0/include"
ignoring nonexistent directory "C:/mingw810/x86_64-810-posix-seh-rt_v6-rev0/mingw64C:/msys64/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../include"
ignoring duplicate directory "C:/ProgramData/chocolatey/lib/mingw/tools/install/mingw64/lib/gcc/../../lib/gcc/x86_64-w64-mingw32/8.1.0/include-fixed"
ignoring duplicate directory "C:/ProgramData/chocolatey/lib/mingw/tools/install/mingw64/lib/gcc/../../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/include"
ignoring nonexistent directory "C:/mingw810/x86_64-810-posix-seh-rt_v6-rev0/mingw64/mingw/include"
#include "..." search starts here:
#include <...> search starts here:
 C:/ProgramData/chocolatey/lib/mingw/tools/install/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/include
 C:/ProgramData/chocolatey/lib/mingw/tools/install/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/include-fixed
 C:/ProgramData/chocolatey/lib/mingw/tools/install/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/include
End of search list.
GNU C17 (x86_64-posix-seh-rev0, Built by MinGW-W64 project) version 8.1.0 (x86_64-w64-mingw32)
        compiled by GNU C version 8.1.0, GMP version 6.1.2, MPFR version 4.0.1, MPC version 1.1.0, isl version isl-0.18-GMP

GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: 985ce7ae6dd3a696cd146ca9896b0035
COLLECT_GCC_OPTIONS='-v' '-ffreestanding' '-c' '-o' 'kernel.o' '-mtune=core2' '-march=nocona'
 C:/ProgramData/chocolatey/lib/mingw/tools/install/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/bin/as.exe -v -o kernel.o C:\Users\Braiden\AppData\Local\Temp\ccTxrZFP.s
GNU assembler version 2.30 (x86_64-w64-mingw32) using BFD version (GNU Binutils) 2.30
COMPILER_PATH=C:/ProgramData/chocolatey/lib/mingw/tools/install/mingw64/bin/../libexec/gcc/x86_64-w64-mingw32/8.1.0/;C:/ProgramData/chocolatey/lib/mingw/tools/install/mingw64/bin/../libexec/gcc/;C:/ProgramData/chocolatey/lib/mingw/tools/install/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/bin/
LIBRARY_PATH=C:/ProgramData/chocolatey/lib/mingw/tools/install/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/;C:/ProgramData/chocolatey/lib/mingw/tools/install/mingw64/bin/../lib/gcc/;C:/ProgramData/chocolatey/lib/mingw/tools/install/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/;C:/ProgramData/chocolatey/lib/mingw/tools/install/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../lib/;C:/ProgramData/chocolatey/lib/mingw/tools/install/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/;C:/ProgramData/chocolatey/lib/mingw/tools/install/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../
COLLECT_GCC_OPTIONS='-v' '-ffreestanding' '-c' '-o' 'kernel.o' '-mtune=core2' '-march=nocona'

objdump -x kernel.tmp

kernel.tmp:     file format pei-x86-64
kernel.tmp
architecture: i386:x86-64, flags 0x00000132:
EXEC_P, HAS_SYMS, HAS_LOCALS, D_PAGED
start address 0x0000000100001000

Characteristics 0x227
        relocations stripped
        executable
        line numbers stripped
        large address aware
        debugging information removed

Time/Date               Sun Jun 21 02:05:38 2020
Magic                   020b    (PE32+)
MajorLinkerVersion      2
MinorLinkerVersion      30
SizeOfCode              00000200
SizeOfInitializedData   00000a00
SizeOfUninitializedData 00000000
AddressOfEntryPoint     00000000ffc01000
BaseOfCode              00000000ffc01000
ImageBase               0000000000400000
SectionAlignment        0000000000001000
FileAlignment           0000000000000200
MajorOSystemVersion     4
MinorOSystemVersion     0
MajorImageVersion       0
MinorImageVersion       0
MajorSubsystemVersion   5
MinorSubsystemVersion   2
Win32Version            00000000
SizeOfImage             ffc07000
SizeOfHeaders           00000400
CheckSum                00006de2
Subsystem               00000003        (Windows CUI)
DllCharacteristics      00000000
SizeOfStackReserve      0000000000200000
SizeOfStackCommit       0000000000001000
SizeOfHeapReserve       0000000000100000
SizeOfHeapCommit        0000000000001000
LoaderFlags             00000000
NumberOfRvaAndSizes     00000010

The Data Directory
Entry 0 0000000000000000 00000000 Export Directory [.edata (or where ever we found it)]
Entry 1 00000000ffc06000 00000014 Import Directory [parts of .idata]
Entry 2 0000000000000000 00000000 Resource Directory [.rsrc]
Entry 3 00000000ffc04000 00000030 Exception Directory [.pdata]
Entry 4 0000000000000000 00000000 Security Directory
Entry 5 0000000000000000 00000000 Base Relocation Directory [.reloc]
Entry 6 0000000000000000 00000000 Debug Directory
Entry 7 0000000000000000 00000000 Description Directory
Entry 8 0000000000000000 00000000 Special Directory
Entry 9 0000000000000000 00000000 Thread Storage Directory [.tls]
Entry a 0000000000000000 00000000 Load Configuration Directory
Entry b 0000000000000000 00000000 Bound Import Directory
Entry c 0000000000000000 00000000 Import Address Table Directory
Entry d 0000000000000000 00000000 Delay Import Directory
Entry e 0000000000000000 00000000 CLR Runtime Header
Entry f 0000000000000000 00000000 Reserved

There is an import table in .idata at 0x6000

The Import Tables (interpreted .idata section contents)
 vma:            Hint    Time      Forward  DLL       First
                 Table   Stamp     Chain    Name      Thunk
 ffc06000       00000000 00000000 00000000 00000000 00000000

The Function Table (interpreted .pdata section contents)
vma:                    BeginAddress     EndAddress       UnwindData
 0000000100004000:      0000000100001010 0000000100001044 0000000100005000
  has negative begin address
  has negative end address
  has negative unwind address
 000000010000400c:      0000000100001044 000000010000108b 000000010000500c
  has negative begin address
  has negative end address
  has negative unwind address
 0000000100004018:      000000010000108b 00000001000010ba 0000000100005018
  has negative begin address
  has negative end address
  has negative unwind address
 0000000100004024:      00000001000010ba 00000001000010dd 0000000100005024
  has negative begin address
  has negative end address
  has negative unwind address

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .text         00000100  0000000100001000  0000000100001000  00000400  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .data         00000010  0000000100002000  0000000100002000  00000600  2**4
                  CONTENTS, ALLOC, LOAD, DATA
  2 .rdata        00000070  0000000100003000  0000000100003000  00000800  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .pdata        00000030  0000000100004000  0000000100004000  00000a00  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .xdata        00000030  0000000100005000  0000000100005000  00000c00  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  5 .idata        00000014  0000000100006000  0000000100006000  00000e00  2**2
                  CONTENTS, ALLOC, LOAD, DATA
SYMBOL TABLE:
[  0](sec -2)(fl 0x00)(ty   0)(scl 103) (nx 1) 0x0000000000000013 Kernel.c
File
[  2](sec  1)(fl 0x00)(ty  20)(scl   2) (nx 1) 0x0000000000000010 SetChar
AUX tagndx 0 ttlsiz 0x0 lnnos 0 next 0
[  4](sec  1)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x0000000000000044 PrintString
[  5](sec  1)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x000000000000008b ClearScreen
[  6](sec  1)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x00000000000000ba _main
[  7](sec  1)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x0000000000000010 .text
AUX scnlen 0xcd nreloc 1 nlnno 0
[  9](sec  2)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x0000000000000000 .data
AUX scnlen 0x8 nreloc 1 nlnno 0
[ 11](sec  5)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x0000000000000000 .xdata
AUX scnlen 0x30 nreloc 0 nlnno 0
[ 13](sec  4)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x0000000000000000 .pdata
AUX scnlen 0x30 nreloc 12 nlnno 0
[ 15](sec  3)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x0000000000000000 .rdata
AUX scnlen 0x29 nreloc 0 nlnno 0
[ 17](sec  3)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x0000000000000030 .rdata$zzz
AUX scnlen 0x3f nreloc 0 nlnno 0
[ 19](sec -2)(fl 0x00)(ty   0)(scl 103) (nx 1) 0x0000000000000015 C:\Users\Braiden\source\repos\Operating System\kernel_entry.asm
File
[ 21](sec  3)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000000070 ___RUNTIME_PSEUDO_RELOC_LIST__
[ 22](sec  2)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000000000 __data_start__
[ 23](sec  1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x00000000000000f0 ___DTOR_LIST__
[ 24](sec  6)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000001000 ___tls_start__
[ 25](sec -1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000400000 __ImageBase
[ 26](sec  3)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000000070 __rt_psrelocs_start
[ 27](sec -1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000000000 __dll_characteristics__
[ 28](sec -1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000001000 __size_of_stack_commit__
[ 29](sec -1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000200000 __size_of_stack_reserve__
[ 30](sec -1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000000005 __major_subsystem_version__
[ 31](sec  6)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000001000 ___crt_xl_start__
[ 32](sec  6)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000001000 ___crt_xi_start__
[ 33](sec  6)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000001000 ___crt_xi_end__
[ 34](sec  6)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000000000 __bss_start__
[ 35](sec  3)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000000070 ___RUNTIME_PSEUDO_RELOC_LIST_END__
[ 36](sec -1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000001000 __size_of_heap_commit__
[ 37](sec  6)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000001000 ___crt_xp_start__
[ 38](sec  6)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000001000 ___crt_xp_end__
[ 39](sec -1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000000000 __dll__
[ 40](sec -1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000000000 __minor_os_version__
[ 41](sec -1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000400000 __image_base__
[ 42](sec -1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000001000 __section_alignment__
[ 43](sec  6)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000000014 __IAT_end__
[ 44](sec  3)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000000070 __RUNTIME_PSEUDO_RELOC_LIST__
[ 45](sec  2)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000000000 WelcomeString
[ 46](sec  2)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000000010 __data_end__
[ 47](sec  1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x00000000000000e0 __CTOR_LIST__
[ 48](sec  6)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000000000 __bss_end__
[ 49](sec  6)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000001000 ___crt_xc_end__
[ 50](sec  6)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000001000 ___crt_xc_start__
[ 51](sec  1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x00000000000000e0 ___CTOR_LIST__
[ 52](sec -1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000000000 __rt_psrelocs_size
[ 53](sec -1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000000200 __file_alignment__
[ 54](sec -1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000000004 __major_os_version__
[ 55](sec  6)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000000014 __IAT_start__
[ 56](sec  6)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000001000 __end__
[ 57](sec  1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x00000000000000f0 __DTOR_LIST__
[ 58](sec -1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000100000 __size_of_heap_reserve__
[ 59](sec  6)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000001000 ___crt_xt_start__
[ 60](sec -1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000000003 __subsystem__
[ 61](sec  6)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000001000 ___tls_end__
[ 62](sec -1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000000000 __major_image_version__
[ 63](sec -1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000000000 __loader_flags__
[ 64](sec  3)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000000070 __rt_psrelocs_end
[ 65](sec -1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000000002 __minor_subsystem_version__
[ 66](sec -1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000000000 __minor_image_version__
[ 67](sec  3)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000000070 __RUNTIME_PSEUDO_RELOC_LIST_END__
[ 68](sec  6)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000001000 ___crt_xt_end__
c
gcc
x86
kernel
osdev
asked on Stack Overflow Jun 20, 2020 by Braiden Grant • edited Jun 20, 2020 by Michael Petch

2 Answers

2

Make sure your custom bootloader is reading in the entire kernel. Have you read enough sectors to make sure the entire kernel is in memory?. The one problem that stands out to me that I can identify in what you have shown is in how you are generating kernel.bin. You do:

objcopy -O binary -j .text  kernel.tmp kernel.bin

This only places the .text section (code) into kernel.bin and nothing else. Your string that isn't printing is likely in the .rdata* sections which you have neglected to include in the kernel. I would include all the sections with:

objcopy -O binary kernel.tmp kernel.bin

This seems to be related to another recent now deleted SO question that was very similar and cross posted to the OSDev Forum. The problem there appears to be the same one here.


The original question was amended by request with additional details. The number of sectors being read was not enough to cover the size of the kernel.

Another issue was identified. The compiler is a 64-bit MinGW Windows compiler; the bootloader only puts the processor in 32-bit protected mode; and the code generated is 64-bit code. You can't properly run 64-bit code in 32-bit protected mode. The code may partially run correctly but it will eventually exhibit unusual and unwanted behaviour.

The choices you have are to put the processor in 64-bit long mode as part of your custom bootloader or have your compiler, assembler, and linker generate 32-bit objects and executables. I touch on this issue in another related Stackoverflow Answer.

You can change nasm to use -felf32 to assemble to 32-bit objects. Since you are using Windows native GCC compilers you can also use -fwin32. To compile GCC code as 32-bit you can use -m32 option and the linker (ld) requires the -mi386pe option. Another option you may wish to use with linking when it comes to OSDev with Windows compilers is LD's -N option which is defined as:

-N, --omagic Do not page align data, do not make text readonly

With all that being said, you can save yourself many hassles by using an i386 or i686 ELF cross compiler if generating 32-bit code and a 64-bit ELF cross compiler if targeting 64-bit code for OS development. More information on building/using Windows Cross compilers can be found in this tutorial and the OSDev wiki has a section on GCC cross compilers in general.


Additional Information

If generating 32-bit Windows objects and executables the non static functions at global scope require an _ to be prepended to them. These underscores are automatically generated by GCC but must be added when you reference them from assembly code. Same applies to assembly functions you create that will be called from C code. You will get an undefined reference if you compile and assemble your code because you declare main this way:

void _main() {

The GCC MinGW compiler will append an underscore to the beginning and the function will be named __main. You would need amend the assembly code to use __main instead of _main as your code currently does. But even easier is to change the declaration to:

void main() {

This will generate a function called _main and that is the function name your assembly code is currently expecting.

64-bit Windows objects and executables do not require or generate functions at global scope with a prefix of _. That is why this isn't an issue when you were generating the 64-bit code.

answered on Stack Overflow Jun 20, 2020 by Michael Petch • edited Jun 20, 2020 by Michael Petch
1

I'd been compiling 64 bit binaries, while I booted into 32 bit protected mode. Compiling and linking them in 32 bit fixed the issue. This raised another issue with the external function prefix "_", which was fixed by just updating the method name so that the prefix didn't cause issues.

my final compile and linking commands:

nasm "C:\Users\Braiden\source\repos\Operating System\Bootloader.asm" -o bootloader.bin -f bin -i "C:\Users\Braiden\source\repos\Operating System"

nasm "C:\Users\Braiden\source\repos\Operating System\kernel_entry.asm" -f elf32 -o kernel_entry.o

nasm "C:\Users\Braiden\source\repos\Operating System\padding.asm" -o padding.bin -f bin

gcc -ffreestanding -m32 -c "C:\Users\Braiden\source\repos\Operating System\Kernel.c" -o kernel.o 

ld -o kernel.tmp -Ttext 0x1000 kernel_entry.o kernel.o -mi386pe

objcopy -O binary kernel.tmp kernel.bin

copy /b bootloader.bin+kernel.bin+padding.bin os-image.img
answered on Stack Overflow Jun 20, 2020 by Braiden Grant

User contributions licensed under CC BY-SA 3.0