Autor Thema: BIOS-Interrupts  (Gelesen 25432 mal)

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« am: 02. April 2011, 19:12 »
Hallo zusammen,

ich habe momentan ein Problem mit meinen BIOS-Interrupts.
Mein System soll den Speicher selbst bestimmen durch 0xe820.
Habe mir dazu Code geschrieben, der in den unreal-mode springt und wieder in den PM springt.
Den Code habe ich gegen Adresse 0x7000 gelinkt und lade ihn auch an die Stelle.
In meinem Kernel rufe ich folgenden Assembler-Befehl:
call *0x7000
Leider laedt er nicht 0x7000 in EIP sondern den Inhalt von 0x7000.
Wenn ich es mit
call (0x7000)
probiere, kommt nichts sinnvolles bei raus. Das was dann in EIP steht, kann ich in meinem Code nicht finden.

Wie sieht er richtige Befehl aus?

Danke.

Grusz
rizor
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

sfan

  • Beiträge: 94
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 02. April 2011, 20:06 »
Wie wär's mit
call 0x7000
?
« Letzte Änderung: 30. April 2013, 23:06 von sfan »

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 02. April 2011, 21:25 »
Das geht auch nicht. Da versucht er auch auf komische Adressen zuzugreifen.
Keine Ahnung, woher er die Werte bekommt.
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

sfan

  • Beiträge: 94
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 02. April 2011, 21:30 »
Wäre es nicht möglich
mov eip, 7000h
zu benutzen?
« Letzte Änderung: 30. April 2013, 23:05 von sfan »

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 02. April 2011, 21:52 »
Das laesst GAS nicht zu. Da sagt er mir, dass EIP das falsche Register ist.
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 02. April 2011, 23:14 »
EIP kann man weder lesen noch schreiben. Darum geht keine IP-relative Adressierung. Es lässt sich nur über CALL und JMP verändern.

freecrac

  • Beiträge: 86
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 03. April 2011, 02:57 »
EIP kann man weder lesen noch schreiben. Darum geht keine IP-relative Adressierung. Es lässt sich nur über CALL und JMP verändern.

Wir können auch eine Adresse auf den Stack schieben und dann ein Rücksprung machen.

Dirk

sfan

  • Beiträge: 94
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 03. April 2011, 08:37 »
Wenn "call *0x7000" den Inhalt von 0x7000 nach EIP lädt und nicht 0x7000, dann müsste
var db 0x7000
call var
doch 0x7000 nach EIP laden.
Das ist doch das Ziel!


Sfan

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 03. April 2011, 10:46 »
Normalerweise macht man das so:
mov $0x7000, %eax
call *%eax

oder lädt gleich das Segment dazu:
lcall $0x08,$0x7000
Dieser Text wird unter jedem Beitrag angezeigt.

sfan

  • Beiträge: 94
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 03. April 2011, 12:34 »
Normalerweise macht man das so:
mov $0x7000, %eax
call *%eax
Das geht natürlich auch!
Meine Methode sollte aber möglichst nichts an den Regtistern ändern.


Sfan

MNemo

  • Beiträge: 547
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 03. April 2011, 17:14 »
also laut AMD-Manuals gibt es keinen
call immfür absolute adressen

es bleiben dir also nur die drei möglichkeit: far call, eax oder var
„Wichtig ist nicht, besser zu sein als alle anderen. Wichtig ist, besser zu sein als du gestern warst!“

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #11 am: 03. April 2011, 19:55 »
Meine Methode sollte aber möglichst nichts an den Regtistern ändern.
Programme, die nichts an den Registern ändern, müssen ziemlich langweilig sein.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #12 am: 04. April 2011, 17:54 »
Okay, jetzt wird der Code ausgefuehrt, macht aber ein paar Zicken, sobald ich in den RM springe.
Hier ist mal der Code:

.code16gcc

int_e820:
xor %ebx, %ebx
xor %bp, %bp
mov $0x8004, %eax
mov %eax, %edi
mov $0x0534D4150, %edx
mov $0xe820, %eax
mov $24, %ecx
int $0x15
jc exit
cmp %eax, %edx
jnz exit
cmp %ebx, 0x0
jz exit
jmp check
loop:
mov $0x1, %eax
mov %eax, 0x14(%edi)
mov $24, %ecx
int $0x15
jc exit
mov $0x0534D4150, %edx
check:
jcxz bad_entry
cmp %cl, 20
jbe check_length
mov 20(%edi), %ecx
test $0x1, %ecx
je bad_entry
check_length:
mov 0xc(%edi), %ecx
or 0x8(%edi), %ecx
jz bad_entry
inc %bp
add 24, %edi
bad_entry:
test %ebx, %ebx
jne loop
exit:
mov %bp, (0x8000)
clc
mov %cr0, %eax
or 0x1, %eax
mov %eax, %cr0
push $0x8
push $goback
retf

In den RM springe ich, indem ich einfach das PM-Bit loesche.
Sollte doch funktionieren, oder?
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #13 am: 04. April 2011, 19:03 »
So einfach ist das nicht.

Wie das geht, steht hier: http://wiki.osdev.org/Real_mode#Switching_from_Protected_Mode_to_Real_Mode
Dieser Text wird unter jedem Beitrag angezeigt.

sfan

  • Beiträge: 94
    • Profil anzeigen
Gespeichert
« Antwort #14 am: 04. April 2011, 20:27 »
Meine Methode sollte aber möglichst nichts an den Regtistern ändern.
Programme, die nichts an den Registern ändern, müssen ziemlich langweilig sein.
Nur das kleine Codestück sollte nichts an den Registern ändern



Sfan

freecrac

  • Beiträge: 86
    • Profil anzeigen
Gespeichert
« Antwort #15 am: 05. April 2011, 00:05 »
Okay, jetzt wird der Code ausgefuehrt, macht aber ein paar Zicken, sobald ich in den RM springe.
Hier ist mal der Code:
....

Wird diesen 16 Bit-RM-Bios-Interrupt vom Virtual 8086 Mode aus aufgerufen, denn sonst zickt dieser Bios-Interrupt schon selber sogar noch bevor in den RM geschaltet wird herum?

Dirk
« Letzte Änderung: 05. April 2011, 00:08 von freecrac »

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #16 am: 14. April 2011, 20:49 »
Die Frage verstehe ich nicht. Der Kernel soll in den Unrealmode springen und dort den Interrupt ausfuehren. Das muesste funktionieren.
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #17 am: 15. April 2011, 02:00 »
Du willst die BIOS-Interrupts im Unrealmode ausführen? Geht das überhaupt zuverlässig, denn so ein BIOS-Code kann ja sonstwas tun?

freecrac

  • Beiträge: 86
    • Profil anzeigen
Gespeichert
« Antwort #18 am: 15. April 2011, 07:29 »
Du willst die BIOS-Interrupts im Unrealmode ausführen? Geht das überhaupt zuverlässig, denn so ein BIOS-Code kann ja sonstwas tun?
Bios-Interrupts lassen sich entweder im RM, oder im V86-Mode, oder im 16 Bit-Unrealmode ausführen, aber nicht im PM.
Erst wenn erneut in den PM geschaltet wird und Segmente geladen werden mit anderen Einträgen bei der Segmentgrößße im dortigen GDT,
dann wird diese Segmentgröße in die Schattenregister geschrieben.

Mir ist kein Bios-Interrupt bekannt der selber in den PM schaltet und wieder zurückin den RM. (Mainboad mit EFI-Bios?)

Dirk

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #19 am: 16. April 2011, 22:37 »
Hallo,


während meiner Schulzeit, also vor sehr vielen Jahren, hab ich und ein Kumpel mal versucht ein RM-Programm zu bauen das mit Hilfe von FS und GS mehr als 64 kB ansprechen sollte. Wir haben FS und GS auch anständig im PM initialisiert und sind korrekt in den RM zurückgesprungen. Das System lief auch ganz normal weiter aber irgendwann gab es dann eine GP-Exception wenn über FS oder GS mit einem Offset größer 64 kB zugegriffen wurde. Unsere Lösung war das wir einen passenden Excpetion-Handler in die RM-IDT eingetragen haben (für INT 0x0D) der einfach nur in den PM ging, FS und GS wieder passend initialisierte und dann zurück im RM ein IRET gemacht hat. Mit diesem Trick konnten wir die durchschnittliche Laufzeit unseres Programm deutlich steigern aber irgendwann krachte es trotzdem wegen irgendeiner unbehandelten Exception. Soweit ich mich noch erinnern kann hatten wir einfach Probleme im RM genau zu analysieren ob der INT nun wirklich eine Exception ist oder eben ein IRQ 5 (ein INT 0x0D wäre zwar auch möglich gewesen aber das hatten wir einfach mal ignoriert). Eigentlich sollte das kein Problem sein aber mit dem PIC kannten wir uns damals nicht so richtig aus. Einen Dissasembler der den Befehl auf den der IP auf dem Stack zeigt genau analysiert um zu erkennen ob das ein Speicherzugriff ist oder nicht erschien uns damals als zu aufwendig und einfach immer in den PM zu gehen kostete enorm viel Performance und löste das Problem trotzdem nicht vollständig. Zumindest nicht bei Programmen die die Soundkarte (welche ja IRQ 5 wollte) benutzt haben. Aber auch wenn es keinen IRQ 5 gab hielt unser Schmalspur-UnReal-Mode nicht ewig.

Es ist zwar durchaus möglich das wir das damals nicht ordentlich implementiert haben und es deswegen nicht stabil lief aber von einer ernsthaften/längeren Benutzung des UnReal-Mode kann ich persönlich trotzdem einfach nur abraten.


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

 

Einloggen