Autor Thema: rets gehen nicht (pm)  (Gelesen 12301 mal)

Gawag

  • Beiträge: 14
    • Profil anzeigen
Gespeichert
« am: 16. November 2005, 21:31 »
Hi
Also irgendwie funktionieren im PM die ret's nicht.

im RM konnte ich ganz einfach sowas machen:


...
call print
...
print:
...
ret

und nach dem ret landete ich dann wieder direkt nach dem call.
im PM startet der Rechner einfach nur neu.
Die Funktion wird richtig ausgeführt, nur das ret zurück geht eben nicht.

Muss man das im PM irgendwie anders machen?

Ich hab übrigens auch andere ret's wie iret und iretd probiert, genau dasselbe.

Bin übrigens erst seit etwa zwei Tagen mit dem PM zugange also noch ziemlich unerfahren.  :)

EDIT: Achja das wollte ich ja auch noch fragen: Was ist eigentlich der Unterschied zwischen den verschiedenen ret's? also iret, iretd und retd.
ehem... kommt noch

SSJ7Gohan

  • Beiträge: 398
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 16. November 2005, 21:44 »
IRET und IRETD werden benutzt, um aus einem Interrupt zurückzukehren.
Ein normales Ret sollte eigentlich auch im PMode funktionieren. Hast du einen gültigen Stack und hast du die GDT richtig geladen?

Gawag

  • Beiträge: 14
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 16. November 2005, 21:50 »
hm....

also irgendwie ist das mit dem Neustart weg... scheint zu gehen.

Ich hatte im Kernel erst einen 16Bit Bereich, dann einen 32Bit und dann wieder einen 16Bit und noch einen 32Bit Bereich. Jetzt hab ich das mal anders sortiert so dass die beide zusammen liegen (also erst der ganze 16 Bit Code und dann der ganze 32Bit Code).

Aber was ist nen nun der Unterschied zwischen den vielen ret's?
Hab da irgendwie nichts von in nem Tutorial gesehen.
ehem... kommt noch

Gawag

  • Beiträge: 14
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 16. November 2005, 21:53 »
Ach da wa ja ne Antwort.  :D
Also das Problem ist jetzt behoben aber das mit den Rets verstehe ich noch nicht ganz genau. Also iret bzw. iretd braucht man nur bei einer Interruptfunktion (also bei denen aus der IDT)?

Und was ist nun mit den beiden ret's mit einem d am Ende?
ehem... kommt noch

SSJ7Gohan

  • Beiträge: 398
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 16. November 2005, 21:59 »
RET popt EIP vom Stack. IRET/IRETD popen EIP, CS und EFLAGS vom Stack, und können so benutzt werden, um in Ring3 Code zurückzukehren, der in einem anderen Segment liegt. RETD ist soweit ich weiß das normale PM RET, das 32 Bit Addressen benutzt. RETN ist eine Mnemonic für RET. RETF popt EIP und CS.

Normalerweise braucht man im PM nur IRET für Interrupts und RET für alles andere. Gelegentlich eventuell noch RETF um in ein anderes Segment zu returnen.

Eine gute Instructionset Beschreibung gibts im nasm Manual sowie in den offiziellen x86 Spezifikationen von Intel.

Gawag

  • Beiträge: 14
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 16. November 2005, 23:14 »
Aha. Danke schonmal. :-)

Das Problem ist doch noch nicht gelöst. Hab den kleinen Unterschied erst jetzt bemerkt.

Also bei einem ret startet der Rechner neu.
Bei einem retd springt er zu einer ganz anderen Stelle/Funktion als er eigentlich hin sollte.

Ich vermute bei einem ret springt er ebenfalls zu einer ganz anderen Stelle die ihn eben neustarten lässt.

Hat jemand ne Idee warum er ganz woanders landet? Kann das wirklich an einer falschen GDT oder nem falschen Stack liegen?

Alle anderen Funktionen scheinen übrigens zu funktionieren. z.B. Schreibzugriff auf den Bildschirmspeicher.

Ich geb euch mal den Code der den Stack betrifft, den kompletten Code kann ich euch leider erst morgen zeigen.
Ist übrigens aus dem PM Tutorial.

mov eax, 2
shl eax, 3

mov ds, ax
mov es, ax
mov ss, ax
mov eax, 0
mov fs, ax
mov gs, ax
mov esp, 0x1FFFFF
ehem... kommt noch

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #6 am: 17. November 2005, 07:15 »
Also tschuldigung das ich das sage, aber wenn ein OS Programmierer den Unterschied von ret und iret nicht kennt. Na ja, ich habe am Anfang ja auch immer blöde Fragen gestellt. Da ich auch gerade am PM in meinem OS dran bin, gebe ich dir hier mal einen Tipp zu deinem Code:

mov eax, 2 shl 3
mov ds, ax
mov es, ax
mov ss, ax
mov eax, 0
mov fs, ax
mov gs, ax
mov esp, 0x1FFFFF


Der Assembler übersetzt so das 2 shl 3 in 16. Das würde bei dir die CPU machen müssen. Also hast du dir hier schonmal CPU-Zeit gespart. ;) Ich verstehe zwar nicht warum du fs und gs auf Null setzt, aber das dürfte ziemlich egal sein wenn du die nicht brauchst. Aber so sieht der Code schon mal eigentlich richtig aus. Wenn bei dir der dritte Eintrag (Eintrag zwei) in der GDT das Datensegment beschreibt müsste der Code richtig sein. Warum er an einer anderen Stelle springt kann ich aus diesem Codestück nicht sagen. Also bei mir klappt das mit der IDT, den calls und den ints ganz gut. Also kannst ja den kompletten Code posten, dann kann ich oder jemand anders dir vielleicht helfen.

OS/M Master
In the Future everyone will need OS-64!!!

nooooooooos

  • Beiträge: 734
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 17. November 2005, 12:22 »
Ich hatte auch mal so ein "ähnliches" Problem. Ich würde dir mal empfehlen den Code für den PM-Jump aus dem Codeschnipsel voM Magazin, Ausgabe 7 zu nehmen. (nichts gegen die Autoren des andern PM-Tut) Bei mir hats nachher geklappt.

Gruss
Noooooooooooooos

Gawag

  • Beiträge: 14
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 17. November 2005, 20:21 »
Also der Code aus Ausgabe 7 hat es nur noch schlimmer gemacht.

Jetzt mal den kompletten Code.
Das ist übrigens so ne art abgewandfelte Form des Codes aus dem PM-Tutorial.

[Bits 16]

call pm_start ; go into pm

mov eax, cr0 ;last step to pm
or eax, 1
mov cr0, eax

db 0xea ;jump to pmode
dw pmode
dw 0x8

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

bootdrv db 0

desc_null:
dd 0
dd 0

desc_code:
dw 0xFFFF
dw 0
db 0
db 0x9A
db 0xCF
db 0

desc_data:
dw 0xFFFF
dw 0
db 0
db 0x92
db 0xCF
db 0

gdt:
limit dw 0
base dd 0

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

pm_start: ; loads the gdt
cli
mov eax, cs
mov ds, ax
shl eax, 4
mov [desc_code+2], ax
mov [desc_data+2], ax
shr eax, 16
mov [desc_code+4], al
mov [desc_data+4], al

mov eax, cs
shl eax, 4
add eax, desc_null
mov [base], eax
mov [limit], word gdt - desc_null - 1

lgdt [gdt]
ret

[Bits 32] ; we are in the pm!

pmode:
mov word [desc_code+2], 0
mov word [desc_data+2], 0
mov byte [desc_code+4], 0
mov byte [desc_data+4], 0

mov eax, 2
shl eax, 3

mov ds, ax
mov es, ax
mov ss, ax
mov eax, 0
mov fs, ax
mov gs, ax
mov esp, 0x1FFFFF

mov al, 0x00
mov dx, 0x03F2
out dx, al                         ;stop the floppy-motor

jmp 0x8:0x10000 + pmode2

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

pmode2: ; now we can do what we want

call test_call

mov edi, 0x000B8400
mov al, 0x5F
call print_number       ; dies drückt das Byte in al als hexadezimale Zahl aus

loop_end:
mov al, ah
jmp loop_end

;times 512-($-$$) db 0 ;darf man das auskommentieren?


test_call:
mov ah, al    ;ist nur eine Testfunktion
ret



Das ist jetzt der eigentliche Kernel. Es gibt noch ein paar andere Dateien aber die haben nichts mit dem PM-Kram zu tun.
ehem... kommt noch

Gawag

  • Beiträge: 14
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 18. November 2005, 00:12 »
Verdammt. Hatte jetzt einen Unterschied zwischen meinem Code und dem aus dem Tutorial gefunde. Hab den ausgeglichen und in Bochs lief es dann auch perfekt. Doch als ich es auf richtiger Hardware ausprobiert habe, startete der Rechner wieder neu.

Noch irgendwelche Ideen? Ich weiß nicht mehr weiter.

Also wie ist das nun genau mit diesem EIP. Ein ret popt diesen vom Stack, also stellt ihn sozusaen wieder her. Und dieser EIP wird von einem call dort hingelegt?
IP steht soviel ich weiß für Instruction Pointer, also der Pointer der auf den aktuellen Befehl zeigt?

Man müsste doch eigentlich so ein ret durch ein
pop eip
ersetzen können doch dann sacht mir nasm was von wegen undefiniertem Symbol. Dasselbe bei IP.
Geht das denn irgendwie? Würde vielleicht weiterhelfen.
ehem... kommt noch

SSJ7Gohan

  • Beiträge: 398
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 18. November 2005, 11:06 »
Den 32 Bit Instruction Pointer (EIP) kann man nicht verändern, man muss dafür JMP, CALL oder RET und ähnliches benutzen. Call pushed den EIP, und RET kehrt dann wieder zur Funktion zurück.

nooooooooos

  • Beiträge: 734
    • Profil anzeigen
Gespeichert
« Antwort #11 am: 18. November 2005, 12:27 »
Komisch, warum es auf dem Computer nicht geht.

Du kannst ja mal den Fehler mit "jmp $" abstecken. "jmp $" bewirkt eine Endlosschleife. Wenn es vor dem Fehler steht startet der Computer nicht neu, weil er in der Endlosschleife ist. Wenn du das "jmp $" nacht dem Fehler platzierst, wird der Computer neustarten.

Gruss
Noooooooooos

Gawag

  • Beiträge: 14
    • Profil anzeigen
Gespeichert
« Antwort #12 am: 18. November 2005, 21:50 »
Also ich hab das jetzt mal mit jump $ ausprobiert und es liegt eindeutig an den ret's.

Noch irgendwelche Ideen?
ehem... kommt noch

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #13 am: 18. November 2005, 22:05 »
nicht die rets sind schuld, sondern der stack. änderst du irgendwas am stackpointer/-selektor, überschreibst du den stack, oder ähnliches?
Dieser Text wird unter jedem Beitrag angezeigt.

Gawag

  • Beiträge: 14
    • Profil anzeigen
Gespeichert
« Antwort #14 am: 20. November 2005, 11:07 »
Ehem.
Also das Problem ist noch immer nicht gelöst aber ich habe da eine Idee...

Benötigt man das A20-Gate um die Adresse 0x1FFFFF im PM anzusprechen?  :oops:

Warum fragt denn keiner nach diesem A20-Gate....
Oder sacht mir das man das braucht...

Hab mich schon gewundert warum das immer so mit zum PM sortiert wird....  :oops:

Naja ich versuchs mal mit diesem A20 Gate.  :D
ehem... kommt noch

nooooooooos

  • Beiträge: 734
    • Profil anzeigen
Gespeichert
« Antwort #15 am: 20. November 2005, 11:13 »
Du brauchst das A20-Gate sicher nicht, wenn du deinen Kernel zu "0x8000"kopierst anstatt zu "0x10000". Ich hatte ja ein ähnliches Problem und zur Lösung beigetragen hat eben auch die Verlegung des Kernels auf 0x8000.

Gruss
Nooooooooos

Gawag

  • Beiträge: 14
    • Profil anzeigen
Gespeichert
« Antwort #16 am: 20. November 2005, 11:23 »
nah sach das doch gleich. Jetzt hab ich schon das A20-Tut durch.  :lol:

Aber erst probier ich das mit dem Kernel verlegen.

...

EDIT: das mt dem kernel verschieben hat nicht geklappt. jetzt versuch ichs mal mit dem A20-gate im Bootloader
ehem... kommt noch

Gawag

  • Beiträge: 14
    • Profil anzeigen
Gespeichert
« Antwort #17 am: 20. November 2005, 15:41 »
JUHU!
Habs geschafft!
:D

Hab jetzt mal im Bootloader das A20-Gate aktiviert und jetzt l]uft es endlich. :D

Habs jetzt auch mehrfach auf echter Hardware getestet jetzt gets eindeutig.

Am Ende hab ich mir zwar eigentlich selbst geholfen aber trotzdem Danke an alle die es versucht haben.
ehem... kommt noch

nooooooooos

  • Beiträge: 734
    • Profil anzeigen
Gespeichert
« Antwort #18 am: 20. November 2005, 17:26 »
Nur so ne Frage: Wie hast du es selbst geschafft ? Für alle die einmal das selbe Problem haben werden ???

Gruss
Nooooooooos

hannibal

  • Host
  • Beiträge: 400
    • Profil anzeigen
    • brainsware - the rock.
Gespeichert
« Antwort #19 am: 20. November 2005, 18:59 »
hat er doch geschrieben..das A20 gate war nicht aktiviert.
\\o
o//
\o/

 

Einloggen