Autor Thema: Sprung in den RealMode  (Gelesen 13517 mal)

üäpöol

  • Beiträge: 110
    • Profil anzeigen
Gespeichert
« Antwort #40 am: 02. June 2012, 22:00 »
Ja ... Es werden tatsächlich so viele Sektoren geladen, wie angegeben. Ich frage nur zur Sicherheit nach, ob ich etwas falsch gemacht habe:
    mov ax, 0x1000
    mov es, ax
    mov bx, 0
    mov ah, 2
    mov al, 16
    mov ch, 0
    mov cl, 2
    mov dh, 0
    mov dl, 0
    int 0x13
    jc read
    cmp al, 16
    jne fail
    mov al, '|'
    mov ah, 0x0E
    int 0x10
Hier wird ein | ausgegeben. Ich weiß leider nicht mehr weiter, weil das ja offensichtlich funktioniert.
Achja, eine Idee habe ich noch: Welche Zahl muss ich im Linkerskript für phys angeben? 0x1000 oder 0x0? Mit 0x0 funktioniert noch ein bisschen mehr. Der Kernel wird aber in beiden Fällen geladen. Möglicherweise könnte es auch am Sprung in den PMode liegen? Gibt es eine einfach Möglichkeit zu testen, ob der Sprung geklappt hat?
PS: Schönen Feierabend noch, Jidder! ;)

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #41 am: 02. June 2012, 22:09 »
Da du deinen Kernel für 32-Bit kompilierst, musst du 0x10000 angeben, wenn du ihn an das Segment 0x1000 und Offset 0 lädst.

0x1000 * 16 + 0 = 0x10000

In den Logs deines Emulators sollten hinweise stehen, wenn der Wechsel in den Protected Mode nicht geklappt hat. Zum Beispiel eine Exception. Wenn keine Exception auftritt, solltest du es mit Debugausgaben versuchen.
« Letzte Änderung: 02. June 2012, 22:12 von Jidder »
Dieser Text wird unter jedem Beitrag angezeigt.

üäpöol

  • Beiträge: 110
    • Profil anzeigen
Gespeichert
« Antwort #42 am: 02. June 2012, 23:12 »
Das stimmt nicht ganz, leider. Am Anfang bin ich noch im RealMode. Deshalb gibt es wieder ein paar "truncated relocations". Was ist es dann? Es sieht so aus, als gäbe es keine exception.

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #43 am: 02. June 2012, 23:27 »
Das stimmt nicht ganz, leider. Am Anfang bin ich noch im RealMode. Deshalb gibt es wieder ein paar "truncated relocations".
Nur damit es keine Missverständnisse gibt: Beim Linken, oder?

Du darfst halt keine Symbole (globale C-Funktionen z.B.) im 16-Bit-Code als Operanden verwenden. Kein mov ax, c_main und kein jmp c_main, außer du schreibst vorher [bits 32] (Sag ich mal ohne diese Behauptung jetzt getestet zu haben. Hybriden 16-/32-Bit-Code kann ich auch nicht aus dem Kopf schreiben.)
Dieser Text wird unter jedem Beitrag angezeigt.

üäpöol

  • Beiträge: 110
    • Profil anzeigen
Gespeichert
« Antwort #44 am: 02. June 2012, 23:33 »
Richtig, beim Linken natürlich.
Ich poste einfach mal den Kernel, um Missverständnisse zu vermeiden:
[GLOBAL start]
start:
[BITS 16]
cli
mov eax, cs
mov ds, ax
shl eax, 4
mov [CODE_Desc+2], ax
mov [DATA_Desc+2], ax
shr eax, 16
mov [CODE_Desc+4], al
mov [DATA_Desc+4], al
mov eax, cs
shl eax, 4
add eax, NULL_Desc
mov [Base], eax
mov [Limit], word gdt - NULL_Desc -1
lgdt [gdt]
mov eax, cr0
or eax, 1
mov cr0, eax
db 0xea
dw PMODE
dw 0x8
[BITS 32]
PMODE:
mov word [CODE_Desc+2], 0
mov word [DATA_Desc+2], 0
mov byte [CODE_Desc+4], 0
mov byte [DATA_Desc+4], 0
mov eax, 2 
shl eax, 3
mov ds, ax 
mov ss, ax
mov es, ax
mov eax, 0 
mov fs, ax
mov gs, ax
mov esp, 0x1FFFFF
jmp 0x8:0x10000+PMODE2
PMODE2:
[EXTERN main]
call main
[GLOBAL kernelerror]
kernelerror:
mov byte [0xB8000], 'K'
mov byte [0xB8001], 0x07
mov byte [0xB8002], 'e'
mov byte [0xB8003], 0x07
mov byte [0xB8004], 'r'
mov byte [0xB8005], 0x07
mov byte [0xB8006], 'n'
mov byte [0xB8007], 0x07
mov byte [0xB8008], 'e'
mov byte [0xB8009], 0x07
mov byte [0xB800A], 'l'
mov byte [0xB800B], 0x07
mov byte [0xB800C], 'e'
mov byte [0xB800D], 0x07
mov byte [0xB800E], 'r'
mov byte [0xB800F], 0x07
mov byte [0xB8010], 'r'
mov byte [0xB8011], 0x07
mov byte [0xB8012], 'o'
mov byte [0xB8013], 0x07
mov byte [0xB8014], 'r'
mov byte [0xB8015], 0x07
endless_loop:
cli
hlt

NULL_Desc:
dd 0
dd 0
   
CODE_Desc:
dw 0xFFFF   
dw 0           
db 0           
db 10011010b           
db 11001111b   
db 0           
   
 
DATA_Desc:
dw 0xFFFF
dw 0
db 0
db 0x92
db 0xCF
db 0
 
gdt:
Limit dw 0
Base dd 0
Ich glaube, die main Funktion ist erstmal nebensächlich, außerdem ist sie ziemlich groß. Ist soweit alles richtig? Hier noch das Linkerskript:
OUTPUT_FORMAT("binary")
ENTRY(start)
phys = 0x1000;
SECTIONS
{
  .text phys : AT(phys) {
    code = .;
    *(.text)
    *(.rodata)
    . = ALIGN(0);
  }
  .data : AT(phys + (data - code))
  {
    data = .;
    *(.data)
    . = ALIGN(0);
  }
  .bss : AT(phys + (bss - code))
  {
    bss = .;
    *(.bss)
    . = ALIGN(0);
  }
  end = .;
}

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #45 am: 03. June 2012, 00:30 »
Der Code schon wieder. Ich weiß nicht, warum die Leute glauben, dass sie in der GDT rumfummeln müssen ... Ich und der Autor des Tutorials, aus dem der Code stammt, wissen warum man das macht, und keiner von uns beiden hat Lust das zu erklären. Einer von uns beiden hätte das besser erklären müssen. (Ich bin das nicht.) Deswegen geht das immer schief, wenn die Leute den Code kopieren.

Ich hab mal deine kernel.asm frisiert. Die funktioniert bei mir in qemu.

Die entscheidenen Unterschiede sind, dass ich überall im 16-Bit Code start abziehe, und damit praktisch auf relative Adressierung umsteige.
Dann generiert der Assembler keine globalen Referenzen mehr, weil er das selbst berechnen kann, und der Linker stört sich daran nicht. Das funktioniert, weil der Ladeoffset (=bx) 0 ist. Der Sprung in den Protected-Mode muss dann ein 32-Bit-Sprung sein (db 0x66, ...), weil das Ziel an einer Adresse über 0x10000 liegt, also nicht mehr mit 16-Bit darstellbar ist.

[GLOBAL start]
start:
[BITS 16]
cli
; <------------- unfug gelöscht
mov eax, cs
shl eax, 4
add eax, NULL_Desc-start ; <-------------
mov [Base-start], eax ; <-------------
mov [Limit-start], word gdt - NULL_Desc -1 ; <-------------
lgdt [gdt-start] ; <-------------
mov eax, cr0
or eax, 1
mov cr0, eax
db 0x66 ; <-------------
db 0xea
dd PMODE-start+0x10000 ; <-------------
dw 0x8
[BITS 32]
PMODE:
mov eax, 2 
shl eax, 3
mov ds, ax 
mov ss, ax
mov es, ax
mov eax, 0 
mov fs, ax
mov gs, ax
mov esp, 0x1FFFFF
jmp 0x8:PMODE2 ; <-------------
PMODE2:
[EXTERN main]
call main
[GLOBAL kernelerror]
kernelerror:
mov byte [0xB8000], 'K'
mov byte [0xB8001], 0x07
mov byte [0xB8002], 'e'
mov byte [0xB8003], 0x07
mov byte [0xB8004], 'r'
mov byte [0xB8005], 0x07
mov byte [0xB8006], 'n'
mov byte [0xB8007], 0x07
mov byte [0xB8008], 'e'
mov byte [0xB8009], 0x07
mov byte [0xB800A], 'l'
mov byte [0xB800B], 0x07
mov byte [0xB800C], 'e'
mov byte [0xB800D], 0x07
mov byte [0xB800E], 'r'
mov byte [0xB800F], 0x07
mov byte [0xB8010], 'r'
mov byte [0xB8011], 0x07
mov byte [0xB8012], 'o'
mov byte [0xB8013], 0x07
mov byte [0xB8014], 'r'
mov byte [0xB8015], 0x07
endless_loop:
cli
hlt

NULL_Desc:
dd 0
dd 0
   
CODE_Desc:
dw 0xFFFF   
dw 0           
db 0           
db 10011010b           
db 11001111b   
db 0           
   
 
DATA_Desc:
dw 0xFFFF
dw 0
db 0
db 0x92
db 0xCF
db 0
 
gdt:
Limit dw 0
Base dd 0

Damit der Code funktioniert, musst du im Linkerskript phys auf 0x10000 setzen. Mich wundert, dass das setzen der Ladeadresse funktioniert. Ich würde eher die Linkadresse setzen, also so:
OUTPUT_FORMAT("binary")
ENTRY(start)
SECTIONS
{
  . = 0x10000;
  .text : {
    code = .;
    *(.text)
    *(.rodata)
    . = ALIGN(0);
  }
  .data :
  {
    data = .;
    *(.data)
    . = ALIGN(0);
  }
  .bss :
  {
    bss = .;
    *(.bss)
    . = ALIGN(0);
  }
  end = .;
}
« Letzte Änderung: 03. June 2012, 00:33 von Jidder »
Dieser Text wird unter jedem Beitrag angezeigt.

üäpöol

  • Beiträge: 110
    • Profil anzeigen
Gespeichert
« Antwort #46 am: 03. June 2012, 00:39 »
Wow, der Code funktioniert. Das ist schonmal super, weil ich jetzt endlich anfangen kann, einen funktionierenden Code zu verstehen. :) Vielen Dank. Wenn ich noch Fragen habe, melde ich mich.

 

Einloggen