Hasta ahora, lo estaba desarrollando en Windows, usando Nasm y MinGW, pero me encontré con el problema de las cadenas y lo porté a GNU/Linux.
En Windows, mi linker script es este:
Código
OUTPUT_FORMAT("pe-x86-64") ENTRY("loader") SECTIONS { . = 0x100000; .text : { code = .; *(.text) text_end = .; } .rodata : { rodata = text_end; *(.rodata) *(.rdata) rodata_end = .; } .data : { data = rodata_end; *(.data) data_end = .; } .bss : { bss = data_end; *(.bss) bss__end = .; } end = .; }
Y compilo todo, con el siguiente bat:
Código:
@echo off
set nasm="tools\nasm.exe"
set bochs="C:\Program Files (x86)\Bochs-2.5.1\bochs.exe"
set fat12maker="tools\fat12maker.exe"
set ld="..\MinGW64\bin\x86_64-w64-mingw32-ld.exe"
set cpp="..\MinGW64\bin\x86_64-w64-mingw32-g++.exe"
set objcopy="..\MinGW64\bin\x86_64-w64-mingw32-objcopy.exe"
set cpp_params=-I.\Kernel\ -nostdlib -nostartfiles -nodefaultlibs -masm=intel -fstrength-reduce -fomit-frame-pointer -finline-functions -nostdinc -fno-builtin
mkdir bin\
%nasm% -fbin bootloader\Stage_1.asm -o Stage_1.bin
if NOT %ERRORLEVEL%==0 goto error
%nasm% -fbin bootloader\Stage_2.asm -o Stage_2.bin
if NOT %ERRORLEVEL%==0 goto error
%cpp% %cpp_params% -c Kernel\kernel.cpp -o bin\kernel.o
%cpp% %cpp_params% -c Kernel\Drivers\screen.cpp -o bin\screen.o
%cpp% %cpp_params% -c Kernel\string.cpp -o bin\string.o
%cpp% %cpp_params% -c Kernel\io.cpp -o bin\io.o
%cpp% %cpp_params% -c Kernel\idt.cpp -o bin\idt.o
%nasm% -f win64 Kernel\Stage_3.asm -o bin\Stage_3.o
if NOT %ERRORLEVEL%==0 goto error
%ld% -nostdlib -nodefaultlibs -T linker.ld bin\Stage_3.o bin\kernel.o bin\idt.o bin\screen.o bin\string.o bin\io.o -o Kernel.out
%objcopy% -x -g -X -S -O binary Kernel.out kernel.bin
copy /b Stage_2.bin+kernel.bin Stage_2.bin
if NOT %ERRORLEVEL%==0 goto error
%fat12maker% -b Stage_1.bin -i Stage_2.bin -o Kernel.img
%bochs% -f bochsconf
goto fin
:error
echo Se produjo un error de compilacion
exit
:fin
echo Compilacion satisfactoria
rmdir /S /Q bin\
Se ejecuta bien, pero no se muestran las cadenas que son constantes globales. No puedo hacer algo como esto:
Código
const char * interrupts_exceptions[] = { "0 - Division by zero exception", "1 - Debug exception", "2 - Non maskable interrupt", "3 - Breakpoint exception", "4 - 'Into detected overflow", "5 - Out of bounds exception", "6 - Invalid opcode exception", "7 - No coprocessor exception", "8 - Double fault", "9 - Coprocessor segment overrun", "10 - Bad TSS", "11 - Segment not present", "12 - Stack fault", "13 - General protection fault", "14 - Page fault", "15 - Unknown interrupt exception", "16 - Coprocessor fault", "17 - Alignment check exception", "18 - Machine check exception", "19 - Reserved exception", "20 - Reserved exception", "21 - Reserved exception", "22 - Reserved exception", "23 - Reserved exception", "24 - Reserved exception", "25 - Reserved exception", "26 - Reserved exception", "27 - Reserved exception", "28 - Reserved exception", "29 - Reserved exception", "30 - Reserved exception" "31 - Reserved exception"}; void idt::init_idt() { idt_ptr = (idt_ptr_t*)IDT_ADDRESS; *idt_entries = (idt_entry_t*)IDT_ADDRESS; clean_gates(); screen::kprintf("Exceptions pointer: 0x%p\n", ::interrupts_exceptions); screen::kprintf("String: %s\n", ::interrupts_exceptions[0]); //<-------------------------- idt_set_gate(0, (QWORD)isr0, 0x08, 0x8E); }
Esto es lo que muestra: http://forum.osdev.org/download/file.php?id=2342&mode=view
Estuve buscando información en http://wiki.osdev.org/Main_Page pero no consigo arreglar el problema.
El linker script de linux es este:
Código
OUTPUT_FORMAT(binary) ENTRY(loader) SECTIONS { . = 0x100000; .text : { code = .; *(.text) text_end = .; } .rodata : { rodata = text_end; *(.rodata) rodata_end = .; } .data : { data = rodata_end; *(.data) data_end = .; } .bss : { bss = data_end; *(.bss) bss__end = .; } end = .; }
Y el Makefile:
Código
CPP = g++ CPP_PARAMS = -I./Kernel/ -nostdlib -nostartfiles -nodefaultlibs -masm=intel -fstrength-reduce -fomit-frame-pointer -finline-functions -nostdinc -fno-builtin OBJECTS = Stage_3.o kernel.o screen.o string.o io.o idt.o FAT12MAKER = ./tools/fat12maker/fat12maker all: nasm -fbin bootloader/Stage_1.asm -o Stage_1.bin nasm -fbin bootloader/Stage_2.asm -o Stage_2.o nasm -felf64 Kernel/Stage_3.asm -o Stage_3.o $(CPP) $(CPP_PARAMS) -c Kernel/kernel.cpp -o kernel.o $(CPP) $(CPP_PARAMS) -c Kernel/Drivers/screen.cpp -o screen.o $(CPP) $(CPP_PARAMS) -c Kernel/string.cpp -o string.o $(CPP) $(CPP_PARAMS) -c Kernel/io.cpp -o io.o $(CPP) $(CPP_PARAMS) -c Kernel/idt.cpp -o idt.o ld -nostdlib -nodefaultlibs -T linker-linux.ld $(OBJECTS) -o Kernel.o cat Stage_2.o Kernel.o > Stage_2.bin $(FAT12MAKER) -b Stage_1.bin -i Stage_2.bin -o Kernel.img bochs -f bochsconf-linux clean: rm *.o rm *.bin
Pero en Linux, funciona peor. Sólo funcionan las cadenas que se declaran como variables locales:
Código
extern "C" void kmain(WORD Foo, WORD Foo2) { char saludo[] = "Hello!\n"; screen::clear_screen(); screen::hide_cursor(); screen::kprintf("Adios\n"); //No funciona screen::kprintf(saludo); //Funciona
Estoy muy perdido, espero que alguien pueda echarme una mano...
Saludos.