Hola, estoy desarrollando un Kernel y tengo un problema con los strings. El Kernel bootea desde la disquetera, carga el Stage2 y entra en modo largo, luego se inicia el Kernel en C++.
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:
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:
@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:
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=viewEstuve buscando información en
http://wiki.osdev.org/Main_Page pero no consigo arreglar el problema.
El linker script de linux es este:
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:
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:
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.