Autor Thema: Ausgabe eines Zeichens im PMode via Videospeicher  (Gelesen 6346 mal)

ZettaME

  • Beiträge: 4
    • Profil anzeigen
Gespeichert
« am: 01. August 2004, 21:22 »
Hallo Allerseits,

ich beziehe mich auf das Tutorial von TeeJay (Protected Mode Tutorial). Nun denn - ich habe versucht den dort beigestellten Download-Code (kernel16.asm) dahingehen zu verändern, dass am Schluß eine einfache Zeichenausgabe über den Videospeicher erfolgt.

nach der Marke PMODE2:

habe ich dann folgendes eingefügt:

   MOV BYTE [0xB8000], 'z'
   MOV BYTE [0xB8001], 0x07

habe sonst nichts am Code verändert! Es erfolgt jedoch nicht die gewünschte Ausgabe am Bildschirm.

In einer anderen Variante hab ich vor dem letzten FAR JUMP, dann dies eingefügt und die Ausgabe am Bildschirm erfolgte nach dem Bootvorgang:

   ;(Auszug aus dem modifizierten Code (Original TeeJay))
   .
   .
   .
   
   MOV BYTE [0xB8000], 'z'
   MOV BYTE [0xB8001], 0x07
 
   jmp  0x8:0x10000 + PMODE2 ;Sprung in das "neue" Codesegment
   
PMODE2:

   .
   .
   .


Hat jemand einen Tip oder eine Lösung, wie es im 1. Fall funktionieren kann?

Vielen Dank!

Gruß

ZettaME

Franz1299

  • Beiträge: 37
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 02. August 2004, 07:10 »
Du musst an 0xA8000 schreiben, da der Codedeskriptor nach dem jump am phy. Offset 0x10000 beginnt. Also 0xB8000 - 0x10000 = 0xA8000

Roshl

  • Beiträge: 1 128
    • Profil anzeigen
    • http://www.lowlevel.net.tc
Gespeichert
« Antwort #2 am: 02. August 2004, 08:41 »
Das ist leider so nicht richtig. Nach der Marke PMODE2 ist der Anfang des Codesegment wieder auf 0. GEnau das selbe gilt für das Datensegment das in dem Falle eigentlich das verantwortliche wäre.
Versuche mal eine Lösung mit stos:
mov edi,0xB8000   ;Adresse das Videospeicher im Textmodus
mov ah,'Z'           ;der buchstabe
mov al,0x07         ;Farbe
;Die Segmente stehen schon richtig also da nix ändern
stosw                 ;nun wird ax zur Addresse an edi verschoben und edi um 2 erhöht also bereit für das nächste Zeichen...
[schild=1]Wieder ein wertvoller(?) Beitrag von Roshl[/schild]

Franz1299

  • Beiträge: 37
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 02. August 2004, 10:50 »
OH ja ich sehe jetzt erst, dass das eine neue Version vom kernel16 ist

ZettaME

  • Beiträge: 4
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 02. August 2004, 13:11 »
@Roshl

hab das mal ausprobiert, funktioniert aber nicht! Hier mal der komplette Code:

;###############################################
[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:

 MOV EDI, 0xB8000
 MOV AH, 'z'
 MOV AL, 0x07
 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:

;#################################################

Hier die variante die funktioniert:


;#################################################

[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


 MOV EDI, 0xB8000
 MOV AH, 'Z'
 MOV AL, 0x07
 STOSW

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

 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:

;##################################################


Es sollte aber ersteres tun...

Viele Dank für Eure Unterstützung :o)

ZettaME

ZettaME

  • Beiträge: 4
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 02. August 2004, 13:15 »
Nachtrag,

wenn ich im 1. Fall 0xA8000 als Videospeicheradresse angebe, passiert ebenfalls nichts...

ZettaME

  • Beiträge: 4
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 03. August 2004, 22:10 »
Habe es gelöst,

mein bootloader hat den Kernel an eine falsche Startadresse geladen.

MfG

ZettaME

 

Einloggen