Autor Thema: Problem mit PM  (Gelesen 4189 mal)

FreakyPenguin

  • Administrator
  • Beiträge: 301
    • Profil anzeigen
    • toni.famkaufmann.info
Gespeichert
« am: 07. November 2004, 16:23 »
Hallo zusammen
Ich habe den Code vom PM-Tut mal einfach runtergeladen und ein wenig modifiziert:
[BITS 16] ;16 Bit Code erstellen
jmp start ;GDT überspringen

NULL_Desc:
dd 0
dd 0

CODE_Desc:
dw 0xFFFF ;Segmentgröße Byte 0/1
dw 0 ;Segmentbasisadresse Byte 0/1
db 0 ;Segmentbasisadresse Byte 2
db 10011010b ;Zugriffsberechtigungen
db 11001111b ;Zusatz + Segmentgröße Bits 16 - 19
db 0 ;Segmentbasisadresse Byte 3


DATA_Desc:
dw 0xFFFF
dw 0
db 0
db 0x92
db 0xCF
db 0

gdt:
Limit dw 0 ;Größe der GDT (wird später eingetragen)
Base dd 0 ;Adresse der GDT (wird später eingetragen)


start:

cli ;Interrupts ausschalten

mov eax, cs ;EAX auf derzeitiges Codesegment setzen
mov ds, ax ;DS auf Codesegment setzen

shl eax, 4 ;EAX mit 16 multiplizieren (Lineare Adresse
;des Codesegments errechnen)
mov [CODE_Desc+2], ax ;Lineare Adresse des Codesegmentes als
mov [DATA_Desc+2], ax ;Startadresse des Code- und Datendeskriptors
shr eax, 16 ;eintragen
mov [CODE_Desc+4], al
mov [DATA_Desc+4], al

mov eax, cs ;Startadresse der GDT errechnen
shl eax, 4
add eax, NULL_Desc

mov [Base], eax ;Startadresse der GDT eintragen
mov [Limit], WORD gdt - NULL_Desc -1 ;Größe der GDT errechnen und eintragen

lgdt [gdt] ;GDT laden

mov eax, cr0 ;In den Protected Mode schalten,
or eax, 1 ;indem Bit 0 des CR0 Registers auf 1
mov cr0, eax ;gesetzt wird

db 0xea ;FAR-JUMP zum Codesegment
dw PMODE
dw 0x8


[BITS 32] ;32 Bit Code erstellen

PMODE:
mov WORD [CODE_Desc+2], 0 ;Code Segmentstartaddresse auf 0 setzen
mov WORD [DATA_Desc+2], 0 ;Daten Segmentstartadresse auf 0 setzen
mov BYTE [CODE_Desc+4], 0 ;Code Segmentstartaddresse auf 0 setzen
mov BYTE [DATA_Desc+4], 0 ;Daten Segmentstartadresse auf 0 setzen

mov eax, 2 ;Selektor für das Datensegment erstellen
shl eax, 3

mov ds, ax ;Daten- Stack- und Extrasegment mit
mov ss, ax ;Datensegmentdeskriptor laden
mov es, ax
mov eax, 0 ;FS und GS mit Null-Deskriptor laden
mov fs, ax
mov gs, ax
mov esp, 0x1FFFFF ;Stack auf unterhalb der 2 MB Grenze setzen

jmp 0x8:0x10000 + PMODE2 ;Sprung in das "neue" Codesegment

PMODE2:
dw 0x0746
mov EDI, 0xB8002
mov ax, WORD[PMODE2+1]

stosw
jmp END ;Zum Ende Springen

times 512-($-$$) db 0; ;Da der Linker sich nicht mit ungeraden
;Dateigrößen verträgt, wird diese Datei auf 512
;gepaddet.

END:


Nun, wenn ich diesen code mit dem bootloader lade startet der pc einfach neu. Kann mir jemand helfen ?


Gruss Togi[/code]

FreakyPenguin

  • Administrator
  • Beiträge: 301
    • Profil anzeigen
    • toni.famkaufmann.info
Gespeichert
« Antwort #1 am: 07. November 2004, 16:35 »
ich verwende den Bootloader von TJ


FileSysType db "FAT12   "
BOOTINFOBLOCK_END:

;########################################################################
;BOOTSECTOR_CODE_START

org 0x7C00 ;Code-Start-Adresse auf 0x7C00 setzen

cli ;Interruptflag löschen (keine Interrupts zulassen)
mov ax, 0x9000
mov ss, ax ;Stacksegment auf AX(0x9000) setzen
xor sp, sp ;Stackpointer auf 0 setzen
sti ;Interruptflag setzen (Interrupts wieder zulassen)



call func_FindFileSector ;Startsektor der Kerneldatei finden lassen (Rückgabe in AX)
or ax, ax ;AX = 0? -> Datei nicht gefunden
jz KernelNotFound ;Zur Ausgabe (File not found) springen

call func_ReadFATTable ;FAT-Tabelle in den Speicher lesen lassen

mov bx, 0x1000 ;Segmentadresse festlegen an die der Kernel geladen werden soll
mov dx, [RootEntCnt] ;Startsektor der Datensektoren errechnen
shl dx, 5
add dx, [BytesPerSec]
dec dx
shr dx, 9
add [Temp], dx ;Und das Ergebnis in Temp-Variable speichern


LoadKernelFile:
mov dx, [Temp] ;Startsektor der Datensektoren in DX schreiben
add dx, ax ;Zum Startsektor der Datensektoren den Startsektor der Datei addieren
dec dx ;DX um 2 verringern
dec dx ;Zweimal "dec dx" braucht weniger Bytes als einmal "sub dx, 2"
push bx ;Segmentadresse an die der Sektor gelesen werden soll auf den Stack pushen
push dx ;Sektornummer die gelesen werden soll auf den Stack pushen
call func_ReadSector ;Sektor lesen lassen
add sp, 4 ;2 Parameter vom Stack löschen

push ax ;FAT-Eintrag-Nummer auf den Stack pushen
call func_ReadFATEntry ;Wert des FAT-Eintrags lesen (Rückgabe in AX)
add sp, 2 ;1 Parameter vom Stack löschen

cmp ax, 0xFFF ;Ist das der letzte FAT-Eintrag der Kernel-Datei?
je ExecuteKernel ;Wenn Ja -> Springe zum Kernel
add bx, 32 ;Segmentadresse um 32 erhöhen. Dort wird der nächste Sektor hingelesen
jmp LoadKernelFile ;Springe wieder nach oben um nächsten Sektor der Kernel-Datei zu lesen

ExecuteKernel:
mov ax, 0x1000
push ax ;Segmentadresse an welcher der Kernel ist auf den Stack pushen
mov ax, 0
push ax ;Offsetadresse des Kernels (0) auf den Stack pushen
retf ;Einen FAR-Rücksprung zum Kernel machen

KernelNotFound:
push WORD MsgFileNotFound ;Offset der "File not Found" Meldung auf den Stack pushen
call func_PrintString ;Meldung ausgeben lassen
add sp, 2 ;1 Parameter vom Stack löschen


WaitForKeyToReboot:
mov ah, 0 ;Auf Tastendruck warten
int 0x16

Reboot:
db 0xEA ;Reboot
dw 0x0000
dw 0xFFFF

;BOOTSECTOR_CODE_END
;########################################################################
;DATABLOCK_START

MsgFileNotFound db "File not found.",13,10,0 ;Meldung wenn kein Kernel gefunden wurde

Filename db "KERNEL  BIN" ;Dateiname des Kernels
Temp dw 0 ;Tempvariable

;DATABLOCK_END
;########################################################################
;FUNCTIONS_START

;------------------------------------------------------------------------
;Funktion um einen NULL-Terminierten String auszugebens
;1. Paramtere: Offset an dem sich der String befindet

func_PrintString:
push bp ;BP sichern
mov bp, sp ;Stackpointer in BP übertragen

pusha ;Alle Register sichern

mov si, [Param1] ;1. Parameter(Offset des Strings) nach SI kopieren
mov ah, 0x0E ;Funktion zur Zeichenausgabe
mov bx, 0x0007 ;Farbattribut des Zeichens
.1:
lodsb ;Zeichen von SI-Pointer nach AL kopieren und SI um 1 erhöhen
or al, al ;AL = 0? String zu Ende?
jz .2 ;Wenn JA -> Springe zum Ende
int 0x10 ;Zeichen ausgeben lassen
jmp .1 ;Wieder nach oben springen um nächstes Zeichen auszugeben

.2:
popa ;Register wiederherstellen

mov sp, bp ;Stackpointer wieder in SP übertragen
pop bp ;BP wiederherstellen
ret ;Return

;------------------------------------------------------------------------
;Funktion um den Startsektor der Kernel-Datei zu finden

func_FindFileSector:
push bp ;BP sichern
mov bp, sp ;Stackpointer in BP übertragen
sub sp, 2 ;Platz für eine lokale Variable auf dem Stack schaffen

pusha ;Alle Register sichern

mov ax, 0x9200 ;Segmentadresse festlegen an die ein Sektor zwischengespeichert wird
mov es, ax

mov ax, [FATSize] ;Startsektor des Root-Directorys errechnen
mov bl, [NumFATs]
mul bl
add ax, [ResvdSecCnt]
mov [Temp], ax ;Startsektor des Root-Directorys in Temp-Variable speichern

xor dx, dx ;DX auf 0 setzen (Braucht weniger Bytes als "mov dx, 0")

.E:
cmp dx, [RootEntCnt] ;Wurden schon alle Root-Dir-Einträge durchsucht?
je .A ;Wenn JA -> Datei nicht gefunden

test dx, 15 ;DX durch 16 ohne Rest teilbar?
jnz .B ;Wenn JA -> Nächsten Sektor lesen

push es ;Segmentadresse für zwischenspeichern eines Sektors auf Stack pushen
push ax ;Sektornummer auf Stack pushen
call func_ReadSector ;Sektor lesen lassen
add sp, 4 ;2 Parameter vom Stack löschen
inc ax ;AX um 1 erhöhen (Braucht weniger Bytes als "add ax, 1")
xor bx, bx ;BX auf 0 setzen (Braucht weniger Bytes als "mov bx, 0")

.B: ;Wenn DX NICHT durch 32 OHNE Rest teilbar ist, fahre HIER fort
cmp BYTE [es:bx], 0x0E ;Erstes Zeichen des Root-Dir-Eintrags = 0x0E?
je .D ;Wenn JA -> Nächsten Eintrag lesen
cmp BYTE [es:bx], 0 ;Erstes Zeichen des Root-Dir-Eintrags = 0?
je .A ;Wenn JA -> Keine weiteren Einträge mehr. Datei nicht gefunden


mov si, Filename ;Offset des Dateinamens nach SI kopieren
mov di, bx ;Offset des Root-Dir-Eintrags nach DI kopieren
mov cx, 11 ;11 Zeichen sollen verglichen werden
repe cmpsb ;Solange vergleichen bis CX = 0 oder ungleiche Zeichen
or cx, cx ;CX = 0?
jz .C ;Wenn JA -> Alle Zeichen stimmen überein. Datei gefunden

.D:
inc dx ;DX um 1 erhöhen
add bx, 32 ;BX um 32 erhöhen (Offset des nächsten Root-Dir-Eintrags)
jmp .E ;Wieder nach oben springen um nächsten Eintrag zu vergleichen

.A: ;Wenn die NICHT Datei gefunden wurde, HIER fortfahren
popa ;Alle Register wiederherstellen
xor ax, ax ;AX auf 0 setzen (Braucht weniger Bytes als "mov ax, 0")
jmp .Ende ;Zum Ende Springen

.C: ;Wenn die Datei gefunden wurde, HIER fortfahren
push WORD [es:bx+26] ;Startsektornummer der Datei auf den Stack pushen
pop WORD [Var1] ;Startsektornummer in lokale Variable popen
popa ;Alle Register wiederherstellen
mov ax, [Var1] ;Startsektornummer der Datei nach AX kopieren

.Ende:
mov sp, bp ;Stackpointer in SP übertragen
pop bp ;BP wiederherstellen
ret ;Return

;------------------------------------------------------------------------
;Funktion um einen Sektor zu lesen
;1. Parameter: Logische Sektornummer des Sektors welcher gelesen werden soll
;2. Parameter: Segmentadresse an die der Sektor gespeichert werden soll

func_ReadSector:
push bp ;BP sichern
mov bp, sp ;Stackpointer in BP übertragen
sub sp, 6 ;Platz für 3 lokale Variablen auf dem Stack schaffen

pusha ;Alle Register sichern

;Aus Logischer Sektornummer die CHS Adresse errechnen
mov ax, [Param1] ;Aus logischer Sektornummer den Cylinder errechnen
mov bx, 36
mov dx, 0
div bx
mov [Var1], ax

mov ax, dx ;Aus logischer Sektornummer den Head errechnen
push ax
mov bx, 18
mov dx, 0
div bx
mov [Var2], ax

pop ax ;Aus logischer Sektornummer den Sektor errechnen
mov dx, 0
div bx
mov ax, dx
add ax, 1
mov [Var3], ax


.1:
mov ax, [Param2] ;Segmentadresse zum speichern des Sektors festlegen
mov es, ax
mov bx, 0 ;Offset zum speichern des Sektors festlegen
mov ah, 2 ;Funktion zum Sektorlesen
mov al, 1 ;1 Sektor soll gelesen werden
mov ch, [Var1] ;Angabe des Cylinders an dem der Sektor gelesen werden soll
mov cl, [Var3] ;Angabe des Sektors an dem der Sektor gelesen werden soll
mov dh, [Var2] ;Angabe des Heads an dem der Sektor gelesen werden soll
mov dl, 0 ;Von Laufwerk A: lesen
int 0x13 ;Sektor lesen lassen
jc .1 ;Bei Fehler nochmal versuchen

popa ;Alle Register wiederherstellen

mov sp, bp ;Stackpointer in SP übertragen
pop bp ;BP wiederherstellen
ret ;Return

;------------------------------------------------------------------------
;Funktion um einen FAT-Eintrag zu lesen
;1. Parameter: Nummer des Eintrags der gelesen werden soll
;In AX wird der Wert des gelesenen FAT-Eintrag zurückgegeben

func_ReadFATEntry:
push bp ;BP sichern
mov bp, sp ;Stackpointer in BP übertragen
sub sp, 2 ;Platz für eine lokale Variable auf dem Stack schaffen

pusha ;Alle Register sichern

mov ax, [Param1] ;Offset errechnen an dem sich der FAT-Eintrag im Speicher befindet
mov bx, 3
mul bx
mov bx, 2
xor dx, dx
div bx

mov bx, 0x9200 ;Segmentadresse angeben an der die FAT-Tabelle im Speicher liegt
mov es, bx
mov bx, ax
mov ax, [es:bx]
mov [Var1], ax ;FAT-Eintrag (16 Bit) in lokale Variable speichern

mov cx, [Param1] ;Testen ob der zu lesende FAT-Eintrag gerade oder ungerade ist
test cx, 1
jz .Gerade ;Wenn GERDADE -> Springe

;Wenn der zu lesende FAT-Eintrag UNGERADE ist, HIER fortfahren
popa ;Alle Register wiederherstellen
mov ax, [Var1]
shr ax, 4 ;FAT-Eintrag(12 Bits) aus den 16 Bits extrahieren
jmp .Ende

.Gerade: ;Wenn der zu lesende FAT-Eintrag GERADE ist, HIER fortfahren
popa ;Alle Register wiederherstellen
mov ax, [Var1]
and ax, 0xFFF ;FAT-Eintrag(12 Bits) aus den 16 Bits extrahieren

.Ende:
mov sp, bp ;Stackpointer in SP übertragen
pop bp ;BP wiederherstellen
ret ;Return

;------------------------------------------------------------------------
;Funktion zum einlesen der FAT-Tabelle in den Speicher

func_ReadFATTable:
pusha ;Alle Register sichern

mov bx, 0x9200 ;Segmentadresse festelegen an welche die FAT-Tabelle gelesen werden soll
mov ax, [ResvdSecCnt] ;Startsektor der FAT-Tabelle eintragen
mov cx, [FATSize] ;Anzahl der FAT-Tabellen-Sektoren eintragen
.A:
push bx ;Segmentadresse auf den Stack pushen
push ax ;Sektornummer auf den Stack pushen
call func_ReadSector ;Sektor lesen lassen
add sp, 4 ;2 Parameter vom Stack löschen
inc ax ;Nächsten Sektor auswählen
add bx, 32 ;Segmentadresse um 32 erhöhen (Dort wird nächster Sektor gespeichert)
loop .A ;Solange wiederholen bis alle Sektoren gelesen wurden

popa ;Alle Register wiederherstellen

ret ;Return

;------------------------------------------------------------------------

;FUNCTIONS_END
;########################################################################


times 512-($-$$)-2 db 0 ;Den Rest des Bootsektors mit Nullen Füllen
dw 0AA55h ;0xAA55 am Ende des Bootsektors schreiben

d00m

  • Beiträge: 6
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 09. November 2004, 12:29 »
ähm, ich weiß net, aber kannes sein, das:
du springst in deinem kernel am ende zum END.
jo, und danach?
soweit ich das weiß, bzw. kenne, müsste danach ein, vielelicht, c kernel gelasen werden.
er lädt zwar alles bis runter, aber bei dem sprung zu END ist ja ende, komtm ja nix mehr.
also solltest du, wenn ich das richtig verstehe, entweder eine endlosschleife machen,
oder eine weitere *.asm datei anhängen, die dann dein, z.b. c kernel lädt.

Roshl

  • Beiträge: 1 128
    • Profil anzeigen
    • http://www.lowlevel.net.tc
Gespeichert
« Antwort #3 am: 09. November 2004, 14:23 »
PMODE2:  
   dw      0x0746
   mov       EDI, 0xB8002
   mov       ax, WORD[PMODE2+1]

das dw 0x0746 steht dann genau an dieser stelle, der Prozessor versucht das als code auszuführen und ich glaube das das kein gültiger opcode ist, der Prozessor reagiert sofort mit einen Unknown Opcode  Exception und startet neu
wenn du dir ein zeichen zum test hindrucken lassen willst machs so:
mov WORD [0xB8002],0x0746
da ist alles in einem Op vereint und sollte kein Problem mehr machen
Und dann möchte ich mich doom anschliessen, mach statt dem jmp END ein jmp $ das ist eine endlosschleife da kannst du dann sehen ob alles richtig ausgegeben wurde, sonst versucht er alles als code auszuführen was hinter END liegen könnte
Mehr sollte nich falsch sein^^
[schild=1]Wieder ein wertvoller(?) Beitrag von Roshl[/schild]

FreakyPenguin

  • Administrator
  • Beiträge: 301
    • Profil anzeigen
    • toni.famkaufmann.info
Gespeichert
« Antwort #4 am: 10. November 2004, 20:58 »
Vielen dank ! hat genfunzt !

Hat mir jemand ein macro zum ausgeben ganzer zeichenketten ?
ich krieg das nicht hin.


Gruss Togi

Roshl

  • Beiträge: 1 128
    • Profil anzeigen
    • http://www.lowlevel.net.tc
Gespeichert
« Antwort #5 am: 11. November 2004, 20:07 »
du hast doch schon ne funktion dafür drin
func_PrintString:
   push   bp            ;BP sichern
   mov      bp, sp         ;Stackpointer in BP übertragen
   
   pusha               ;Alle Register sichern
               
   mov      si, [Param1]   ;1. Parameter(Offset des Strings) nach SI kopieren
   mov      ah, 0x0E      ;Funktion zur Zeichenausgabe
   mov      bx, 0x0007      ;Farbattribut des Zeichens
.1:      
   lodsb               ;Zeichen von SI-Pointer nach AL kopieren und SI um 1 erhöhen
   or      al, al         ;AL = 0? String zu Ende?
   jz      .2            ;Wenn JA -> Springe zum Ende
   int      0x10         ;Zeichen ausgeben lassen
   jmp      .1            ;Wieder nach oben springen um nächstes Zeichen auszugeben
       
.2:
   popa               ;Register wiederherstellen

   mov      sp, bp         ;Stackpointer wieder in SP übertragen
   pop      bp            ;BP wiederherstellen
   ret                  ;Return
 musst nur die adresse des string auf den stack pushen und die funktion call'n
also:
push string
call func_PrintString
[schild=1]Wieder ein wertvoller(?) Beitrag von Roshl[/schild]

joachim_neu

  • Beiträge: 1 228
    • Profil anzeigen
    • http://www.joachim-neu.de
Gespeichert
« Antwort #6 am: 11. November 2004, 20:18 »
er ist doch dann im PM. oder soll die für RM sein?
http://www.joachim-neu.de | http://www.orbitalpirates.de | http://www.middleageworld.de

System: 256 RAM, GeForce 2 MX 400, AMD Athlon XP 1600+, Windows XP, 1x Diskette, 1x DVD-ROM, 1x CD-R(W) Brenner,...

zacK

  • Beiträge: 216
    • Profil anzeigen
    • http://www.domae.ch
Gespeichert
« Antwort #7 am: 12. November 2004, 08:02 »
pm = no bios interrupts ;)

hier kannste meine mal guckn..:

mov ax, 0xb800
mov fs, ax

;////////////////////////////////////////////////////////////////////////////////////////////////////////;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;////////////////////////////////////////////////////////////////////////////////////////////////////////;

WriteString:
.0:
push ax

.1:
lodsb
or al, al
jz .2
call WriteChar
jmp .1

.2:
pop ax
ret


;////////////////////////////////////////////////////////////////////////////////////////////////////////;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;////////////////////////////////////////////////////////////////////////////////////////////////////////;

WriteChar:
.0:
push ax
push bx

.1:
mov word bx, [offset_c]
mov byte ah, [TextColor]

mov word [fs:bx], ax
inc bx
inc bx
mov word [offset_c], bx

.2:
pop bx
pop ax
ret

offset_c dw 0


dann aufrufen wie folgt:

mov si, msg
call WriteString


ist halt nicht c-calling..

Roshl

  • Beiträge: 1 128
    • Profil anzeigen
    • http://www.lowlevel.net.tc
Gespeichert
« Antwort #8 am: 12. November 2004, 12:45 »
Ich dachte er wollte im RM welche ausgeben^^
[schild=1]Wieder ein wertvoller(?) Beitrag von Roshl[/schild]

 

Einloggen