Autor Thema: Loader macht nicht weiter...  (Gelesen 6218 mal)

syxce

  • Beiträge: 45
    • Profil anzeigen
Gespeichert
« am: 11. December 2005, 20:29 »
Hallo,
folgendes großes Problem beschäftigt mich nun schon seit mehreren Tagen.
Ich habe meine Bootloader.bin, diese sollte die Dateien kernel.bin und ckernel.bin in den Speicher schreiben damit ich diese später mit jmp erreichen kann, dass macht der auch noch bis zur kernel.bin und gibt dort noch seinen Text aus doch gleich danach wo der Befehl "jmp 08h:01000h" oder auch "jmp 0x1000" steht bricht er ab, also er resetet, ich weiß nicht wiso, er müsste doch eigentlich zur ckernel.bin springen und den code dort ausführen doch das macht er nicht. Ich habe euch mal meine bootloader.bin und meine kernel.bin sowie mein makefile angehängt.
Der ckernel mit seinen zugehörigen includes funktioniert, habe ich bereits getestet doch mit meinem loader und meinem kernel gibts probleme, wenn mir jemand helfen könnte und mir den code abändern könnte wäre ich sehr dankbar.

bootloader.bin:

start:

cli
mov ax, 0x9000
mov ss, ax
mov sp, 0
sti

mov [bootdrv], dl

call kernel

mov ax, 0x1000
mov es, ax
mov ds, ax
push ax
mov ax,0
push ax
retf

bootdrv db 0
loadmsg db "Loading...",13,10,0

putstr:
lodsb
or al, al
jz short putstrd

mov ah, 0x0E
mov bx,0x0007
int 0x10
jmp putstr
putstrd:
retn

kernel:

push ds
mov ax, 0
mov dl, [bootdrv]
int 13h
pop ds
jc kernel

load:
mov ax,0x1000
mov es, ax
mov bx,0

mov ah, 2
mov al, 5
mov cx, 2
mov dx, 0
int 13h
jc load
mov si, loadmsg
call putstr
retn

times 512-($-$$)-2 db 0
dw 0AA55h


kernel.bin
org 0x10000
[BITS 16]       ; We need 16-bit intructions for Real mode

        cli                     ; Disable interrupts, we want to be alone

        mov ax, 0x1000
        mov ds, ax              ; Set DS-register to 0 - used by lgdt

        lgdt [gdt_desc]         ; Load the GDT descriptor

        mov eax, cr0            ; Copy the contents of CR0 into EAX
        or eax, 1               ; Set bit 0
        mov cr0, eax            ; Copy the contents of EAX into CR0

        jmp dword 08h:clear_pipe      ; Jump to code segment, offset clear_pipe


[BITS 32]                       ; We now need 32-bit instructions

clear_pipe:
        mov ax, 10h             ; Save data segment identifyer
        mov ds, ax              ; Move a valid data segment into the data segment register
        mov ss, ax              ; Move a valid data segment into the stack segment register
        mov esp, 090000h        ; Move the stack pointer to 090000h

        mov byte [ds:0B8000h], 'H'      ; Move the ASCII-code of 'P' into first video memory
        mov byte [ds:0B8001h], 1Bh      ; Assign a color code
mov byte [ds:0B8002h], 'a'
mov byte [ds:0b8003h], 1Bh
mov byte [ds:0B8004h], 'l'
mov byte [ds:0b8005h], 1Bh
mov byte [ds:0B8006h], 'l'
mov byte [ds:0b8007h], 1Bh
mov byte [ds:0B8008h], 'o'
mov byte [ds:0b8009h], 1Bh

jmp 08h:01000h   ; Der oben angesprochene jmp

;hang:
;jmp hang


gdt:                    ; Address for the GDT

gdt_null:               ; Null Segment
        dd 0
        dd 0

gdt_code:               ; Code segment, read/execute, nonconforming
        dw 0FFFFh
        dw 0
        db 0
        db 10011010b
        db 11001111b
        db 0

gdt_data:               ; Data segment, read/write, expand down
        dw 0FFFFh
        dw 0
        db 0
        db 10010010b
        db 11001111b
        db 0

gdt_end:                ; Used to calculate the size of the GDT



gdt_desc:                       ; The GDT descriptor
        dw gdt_end - gdt - 1    ; Limit (size)
        dd gdt                  ; Address of the GDT



make.bat
@echo off
nasm -f bin bootloader.asm -o bootloader.bin
nasm -f bin kernel.asm -o kernel.bin

gcc -ffreestanding -c main.c -o main.o
gcc -c video.c -o video.o
gcc -c ports.c -o ports.o

ld -e _main -Ttext 0x1000 -o kernel.o main.o video.o ports.o

ld -i -e _main -Ttext 0x1000 -o kernel.o main.o video.o ports.o
objcopy -R .note -R .comment -S -O binary kernel.o ckernel.bin

copy bootloader.bin+kernel.bin+ckernel.bin os.img



Edit:
wenns jemanden hilft hier noch der ckernel (ohne seine includes):
const char *text1;

void main()
{
  clrscr();
  print(text1);

  for(;;);
}

const char *text1 = "Hallo, Willkommen in C";

syxce

  • Beiträge: 45
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 12. December 2005, 18:39 »
Weiß niemand weiter ?  :(

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 12. December 2005, 21:47 »
hi,

(das folgende sind nur so meine ideen. ohne den vollständigen quelltext kann ich nix testen. was aber nicht heissen soll, dass ich ihn haben will.)

du sagst dem linker ("-tText 0x1000") und dem assembler ("jmp 0x1000"), dass der c-kernel an die adresse 0x1000 geladen wird. da wird er aber nicht hingeladen. es muss ja irgendwas mit 0x1???? sein, oder nich?

außerdem solltest du mal genau überlegen, wo der c-kernel in wirklichkeit hingeladen wird. wenn der (assembler-)kernel z.b. 0x123 bytes groß ist, wird der c-kernel doch an die adresse 0x10123 geladen, oder nicht? soll er da sein? willst du vielleicht den (assembler-)kernel mit times 0x1000-($-$$) db 0 auf die größe 0x1000 bringen?
Dieser Text wird unter jedem Beitrag angezeigt.

syxce

  • Beiträge: 45
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 13. December 2005, 13:00 »
Zitat von: PorkChicken
hi,

(das folgende sind nur so meine ideen. ohne den vollständigen quelltext kann ich nix testen. was aber nicht heissen soll, dass ich ihn haben will.)

du sagst dem linker ("-tText 0x1000") und dem assembler ("jmp 0x1000"), dass der c-kernel an die adresse 0x1000 geladen wird. da wird er aber nicht hingeladen. es muss ja irgendwas mit 0x1???? sein, oder nich?


Wie weiß ich dann wo er sich befindet, damit ich zu ihm jumpen kann ?

Zitat von: PorkChicken

außerdem solltest du mal genau überlegen, wo der c-kernel in wirklichkeit hingeladen wird. wenn der (assembler-)kernel z.b. 0x123 bytes groß ist, wird der c-kernel doch an die adresse 0x10123 geladen, oder nicht? soll er da sein? willst du vielleicht den (assembler-)kernel mit times 0x1000-($-$$) db 0 auf die größe 0x1000 bringen?


Wenn du mir das testen könntest und passend machen könntest wäre dass wirklich nett, deswegen hier die restlichen c-files:


ports.c
unsigned char in(unsigned short _port)
{
  // "=a" (result) means: put AL register in variable result when finished
  // "d" (_port) means: load EDX with _port
  unsigned char result;
  __asm__  ("in %%dx, %%al" : "=a" (result) : "d" (_port));
  return result;
}

void out(unsigned short _port, unsigned char _data)
{
  // "a" (_data) means: load EAX with _data
  // "d" (_port) means: load EDX with _port
  __asm__ ("out %%al, %%dx" : :"a" (_data), "d" (_port));
}



video.c
void clrscr()
{
  unsigned char *vidmem = (unsigned char *)0xB8000;
  const long size = 80*25;
  long loop;

  // Clear visible video memory
  for (loop=0; loop<size; loop++) {
    *vidmem++ = 0;
    *vidmem++ = 0xF;
  }

  // Set cursor position to 0,0
  out(0x3D4, 14);
  out(0x3D5, 0);
  out(0x3D4, 15);
  out(0x3D5, 0);
}

void print(const char *_message)
{
  unsigned short offset;
  unsigned long i;
  unsigned char *vidmem = (unsigned char *)0xB8000;

  // Read cursor position
  out(0x3D4, 14);
  offset = in(0x3D5) << 8;
  out(0x3D4, 15);
  offset |= in(0x3D5);

  // Start at writing at cursor position
  vidmem += offset*2;

  // Continue until we reach null character
  i = 0;
  while (_message[i] != 0) {
    *vidmem = _message[i++];
vidmem += 2;
  }

  // Set new cursor position
  offset += i;
  out(0x3D5, (unsigned char)(offset));
  out(0x3D4, 14);
  out(0x3D5, (unsigned char)(offset >> 8));
}

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 13. December 2005, 14:56 »
Zitat von: syxce
Zitat von: PorkChicken
hi,

(das folgende sind nur so meine ideen. ohne den vollständigen quelltext kann ich nix testen. was aber nicht heissen soll, dass ich ihn haben will.)

du sagst dem linker ("-tText 0x1000") und dem assembler ("jmp 0x1000"), dass der c-kernel an die adresse 0x1000 geladen wird. da wird er aber nicht hingeladen. es muss ja irgendwas mit 0x1???? sein, oder nich?


Wie weiß ich dann wo er sich befindet, damit ich zu ihm jumpen kann ?

einfache mathematik: angenommen der (assembler-)kernel ist 0x123 bytes groß, und du hängst den c-kernel direkt hinter den assembler kernel (copy bootloader.bin+kernel.bin+ckernel.bin os.img). wenn du diesen batzen nun in den speicher an die adresse 0x10000 lädst, befindet sich der assembler-kernel bei 0x10000 und der c-kernel bei 0x10000+0x123 = 0x10123.
Dieser Text wird unter jedem Beitrag angezeigt.

syxce

  • Beiträge: 45
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 13. December 2005, 15:03 »
Auch das habe ich schon probiert aber irgendwie macht der noch immer nicht weiter, ich habe echt keinen plan mehr.

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 13. December 2005, 17:40 »
Zitat von: syxce
Auch das habe ich schon probiert aber irgendwie macht der noch immer nicht weiter, ich habe echt keinen plan mehr.

was meinst du mit "das"?
Dieser Text wird unter jedem Beitrag angezeigt.

syxce

  • Beiträge: 45
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 13. December 2005, 18:34 »
Die Größe des ckernels hinzuaddieren und dann dort hin zu springen.

 

Einloggen