Autor Thema: Segmente richtig setzen  (Gelesen 2917 mal)

scales of justice

  • Beiträge: 228
    • Profil anzeigen
Gespeichert
« am: 27. March 2006, 14:45 »
Hallo,

ich schreib auch grad an meinem eigenen Betriebssystem
es setzt sich aus einem Bootloader (16Bit Assembler) einem Kernel (16Bit Assembler) und einem 2.Kernel (16Bit C) zusammen (soll es jedenfalls mal...)

Den C-Teil könnt ihr euch komplett wegdenken, den gibt es noch nicht
das erwähne ich nur, da ich mal einen C-Teil mit einbauen will und deswegen ld benutzen muss um den Assembler-Kernel zu linken und ihn nicht einfach mit nasm direkt in flat binary umwandeln kann
(als ich den bootloader und den Asm-Kernel mit nasm direkt zu flat-binary gemacht hab, hat übrigens alles problemlos funktioniert)

Mein Problem ist nun folgendes:
der Bootloader funktioniert ohne Probleme
der Assembler-Kernel funktioniert eigentlich auch, außer man greift auf eine festgelegte Adresse zu
(damit meine ich z.B.: 'bsp db "beispiel",0')

sobald man da smacht stürzt das ganze ab
als ichs dann mal in Blochs ausprobiert hab, sagt der:
">>PANIC<< prefetch: RIP > CS:limit"

aus der Meldung, die ja soviel heißt wie "ungültiger Speicherzugriff" und der Tatsache, dass es ohne die o.g. festgelegten Adressen funktioniert, schließe ich das irgendwas mit den Segmenten falsch eingestellt ist
wahrscheinlich im Linker-Script von ld, welches ich ehrlich gesagt auch nur kopiert habe:

OUTPUT_FORMAT("binary")
INPUT(asmkernel.o)
ENTRY(start)
SECTIONS
{
  .text  0x200 : {
    code = .; _code = .; __code = .;
    *(.text)
    . = ALIGN(1);
  }
  .data  : {
    data = .; _data = .; __data = .;
    *(.data)
    . = ALIGN(1);
  }
  .bss  :
  {
    bss = .; _bss = .; __bss = .;
    *(.bss)
    . = ALIGN(1);
  }
  end = .; _end = .; __end = .;
}


in der Zeile ".text  0x200 : {"
muss wahrscheinlich ein anderer Wert rein,
leider weiß ich nicht welcher

ich dachte es muss einfach 0x10000 rein,
da mein Kernel an die Adresse 1000:0000 geladen wird
(das komplette OS ist übrigens im Real-Mode)
aber das wollte ld nicht, dazu sagte er:
"relocation truncated to fit: 16 against `.text'"
und wenn ich den Wert weglasse ändert das auch nichts
immer der gleiche Fehler

hier noch der Quellcode vom Bootloader:

org 7c00h

jmp main

readbr:
mov ah, 02h   ;fest
mov al, 01h   ;Anzahl
mov ch, 00h   ;Spur
mov cl, 02h   ;Sektor
mov dh, 00h   ;Kopf
mov dl, 00h   ;Laufwerksnummer
mov bx, 1000h
mov es, bx    ;Segment
mov bx, 0000h ;Offset
int 13h
ret

main:
call readbr
mov ax, 1000h
push ax
mov ax, 0000h
push ax
retf

int 19h
TIMES 510-($-$$) DB 0
SIGNATURE DW 0xAA55


und hier der vom Asm-Kernel:

text:           ;Anfangsadresse in si übergeben
lodsb
cmp al, 00h
je texte
mov ah, 0Eh
mov bx, 0007h
int 10h
jmp text
texte:
ret

global start
start:
mov si, hello
call text
int 19h
hello db "Kernel started", 13, 10, 0


Ich hoffe ihr könnt mir helfen

nore

  • Beiträge: 76
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 27. March 2006, 15:03 »
also: zunächst einmal sehe ich nirgends, dass du ds initialisierst. das solltest du aber, weil auf variablen normalerweise per ds:offset zugegriffen wird. bzw aus "mov si, hello" wird im prinzip "mov si, ds:hello".

der wert im linker-script ist der abstand vom anfang des segments, in dem du dich befindest, zu der stelle, an der dein code steht.
in deinem fall befindest du dich im segment 0x1000. das heißt, dass die lineare adresse des segmentanfangs 0x10000 ist. an genau diese stelle lädst du aber auch deinen kernel. deshalb ist der oben genantne abstand gleich null , der wert im linker-script muss 0 sein.

hoffe, ich konnte helfen.

cu
  nore

scales of justice

  • Beiträge: 228
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 27. March 2006, 17:03 »
Ich hab jetzt ein paar Änderungen vor genommen und probiert den Fehler ein zu grenzen:

erstmal hab ich im Linkerscript 0x200 auf 0x0 gestellt, wie du es gesagt hast (das neue Linkerscript ist ganz unten)
außerdem initialisiere ich nun auch ds
(bin mir aber nich ganz sicher ob ichs richtig gemacht hab, is unten im Code kommentiert)

so jetzt zur Problem eingrenzung
wenn ich folgenden Code als Asm-Kernel benutze funktioniert das ganze:

global start
start:
cli ;hier wird ds initalisiert
mov ax, cs
mov ds, ax
sti
;mov si, hello
int 19h
hello db "Kernel started", 13, 10, 0
TIMES 512-($-$$) DB 0


sobald ich "mov si, hello" aber nicht mehr auskommentiere, funktioniert es nicht mehr,
Bochs sagt dazu: "prefetch: RIP > CS.limit"

ich versteh aber nicht was der für ein Problem hat
an welchem Limit soll ich denn angekommen sein?
"hello" geht doch nur das Datensegment was an, was hat den CS damit am Hut?

Ach und was ist eigentlich mit dem Stack?
muss ich den nicht auch irgendwie initalisieren?

hier jetzt noch das Linkerscript:

OUTPUT_FORMAT("binary")
INPUT(asmkernel.o)
ENTRY(start)
SECTIONS
{
  .text 0x0 : {
    code = .; _code = .; __code = .;
    *(.text)
    . = ALIGN(1);
  }
  .data  : {
    data = .; _data = .; __data = .;
    *(.data)
    . = ALIGN(1);
  }
  .bss  :
  {
    bss = .; _bss = .; __bss = .;
    *(.bss)
    . = ALIGN(1);
  }
  end = .; _end = .; __end = .;
}


okay, ich habs jetzt hinbekommen,
ch hab nicht nur vergessen ds zu initalisieren sondern auch es
hab hier ein bisschen in den Archiven gestöbert und bin habs dann kapiert
trotzdem danke für deine Hilfe, ohne dich wär ich nich auf die Idee gekommen, dass es an es liegt

auch wenn das Problem jetzt gelöst ist, würde mich noch interessieren wofür es (ich mein das Segment es, nicht ein ding) überhaupt gebraucht wird
bis jetzt hab ich das nur für Schiebeoperationen gebraucht, warum muss ich das dann hier mit 1000 initialisieren?

und warum funktioniert das ganze eigentlich, wenn ich den Asm-Kernel auch direkt mit nasm zu flat-binary mache?
das ergibt für mich gar keinen Sinn

 

Einloggen