Lowlevel
Lowlevel => Lowlevel-Coding => Thema gestartet von: rizor am 14. April 2010, 16:48
-
Nabend zusammen,
ich möchte, dass mein System zurück in den realmode springt, dort arbeitet und dann wieder zurück kommt.
Dabei möchte ich nicht zwei Dateien laden, sondern einfach 16-bit code und 32-bit code zusammenpacken, falls das geht.
Danach soll der 16-bit Code unter die 1MB Grenze geladen werden und dann soll der Code ausgeführt werden.
Ist das möglich?
Danke.
Gruß
rizor
-
Ja das geht. Zumindest hat FreakyPenguin es geschafft seinen trampoline code für SMP-Systeme direkt mitzuassemblieren. Der entsprechende Patch so so aus:
diff --git a/src/loader/loader.ld b/src/loader/loader.ld
30 index 711495b..df7e061 100644
31 --- a/src/loader/loader.ld
32 +++ b/src/loader/loader.ld
33 @@ -13,10 +13,16 @@ SECTIONS
34 *(.data*)^M
35 *(.rodata*)^M
36 }^M
37 - .bss :^M
38 +^M
39 + trampoline_start = LOADADDR(.trampoline);^M
40 + .trampoline 0x7000 : AT(ADDR(.data) + SIZEOF(.data))^M
41 + {^M
42 + *(.trampoline*)^M
43 + }^M
44 + trampoline_end = LOADADDR(.trampoline) + SIZEOF(.trampoline);^M
45 + .bss (LOADADDR(.trampoline) + SIZEOF(.trampoline)) :^M
46 {^M
47 *(.bss*)^M
48 }^M
49 -^M
50 }^M
51 ^M
285 diff --git a/src/loader/trampoline.S b/src/loader/trampoline.S
286 new file mode 100644
287 index 0000000..7461041
288 --- /dev/null
289 +++ b/src/loader/trampoline.S
290 @@ -0,0 +1,45 @@
291 +.section .trampoline,"aw",@progbits
Das wesentliche (fett) ist wohl die Flags der Sektion anzupassen (das ist AT&T-Syntax), außerdem muss man die Linkadresse im Linkerscript natürlich anpassen, zumindest die physische.
-
ah, danke.
Dann werde ich mich daran mal versuchen.
-
Falls ich mal meinen Senf dazugeben darf. Am besten macht sich das wenn man sowas komplett in Assembler schreibt und dann in z.B. NASM nur den Modus angibt (z.b. use16 und use32). Ich habe genau sowas genutzt um in meinem Loader auch aufs BIOS zugreifen zukönnen und trotzdem alles schön in 32bit C-Code zu schreiben.
-
dann bist du aber nicht im protected mode, sonder im realmode. wie es kommt, dass dein 32 bitcode trotzdem funzt weiß ch nicht. auf jeden fall bist du, so denke ich mal, solange nicht im pmode, solange du noch die bios ints nutzen kannst
-
Ich hätte mich besser ausdrücken sollen. Ich springe zurück in den RMode, calle den BIOS-Code und springe zurück in den PMode. So muss ich meinen Loader nicht komplett in ASM coden (was ich vorher gemacht habe) und es macht die Sache halt wesentlich einfacher.
-
Wie darf ich mir das vorstellen?
Du springst in den RMode, machst die BIOS-Interrupts und gehst mit den Ergebnissen zurück in den PMode?
Die Werte in den Registern bleiben bestehen?
Die Idee finde ich noch besser.
Wie kannst du dem Compiler das denn beibringen, dass er 16-bit-Code in einer 32-bit-Umgebung verwenden soll?
-
Ich hab von C aus ne Funktion callBIOS(uint32t *eax, uint32t *ebx, ...) wo du halt Pointer auf die Register (Vars dafür) übergibst. Diese dienen als Eingabe und gleichzeitig als Ausgabe, als Rückgabewert der Funktion habe ich uint32t und gebe die Flags zurück (ist gerade bei BIOS Funktionen wichtig).
Die Funktion habe ich in Assembler geschrieben, zusammengefasst springe ich zurück in den RMode hole die Register vom Stack, rufe den BIOS Int auf, ist dieser fertig packe ich die Register und die Flags wieder auf den Stack und springe zurück in den PMode.
Es ist halt wichtig das du nicht am PIT und nicht am PIC rumspielst solange du sowas machen willst (obwohl ich den PIT solange ich im PMode von meinem eigenem Handler aufrufen lasse).
Wenn du willst könnte ich dir auch den Code als (schlecht kommentiertes) Bsp. geben.
-
Die Frage, die sich mir stellt, ist wie du das ganze linkst.
Ich kenne kein Flag, dass es dem Linker ermöglicht 16-bit und 32-bit-Code zu linken.
Wie machst du das ganze denn?
Liegen die Methoden in eine Sektion, die du dann einfach unter die 1MB-Grenze kopierst?
-
Deswegen musst du das ganze ja in Assembler machen, dem ist es herzlich egal ob er nun die 16bit Variante oder die 32bit Variante von dem Opcode codieren soll und da ich das ganze nur in meinem Loader verwende bin ich auch immer unter der 1MiB Grenze.
Das ganze sieht dann in etwa so aus:
use32
code
...
Sprung in den RMode
use16
.rmode:
code
Sprung in den PMode
use32
.pmode:
Der Linker sieht dann ganz normal eine Elf-Objektdatei und weiß gar nicht das da auch 16bit Code drin ist.
-
Die Frage, die sich mir stellt, ist wie du das ganze linkst.
Ich kenne kein Flag, dass es dem Linker ermöglicht 16-bit und 32-bit-Code zu linken.
Wie machst du das ganze denn?
Siehe den Patch von FreakyPenguin in meinem Beitrag oben. :wink:
Liegen die Methoden in eine Sektion, die du dann einfach unter die 1MB-Grenze kopierst?
exakt das muss man dann machen, jo
edit: Das ganze hat mit Assembler herzlich wenig zu tun. Das einzige Problem mit 16Bit und C/C++ ist wohl eher einen Compiler zu finden, der das unterstützt.
-
Das ganze hat mit Assembler herzlich wenig zu tun. Das einzige Problem mit 16Bit und C/C++ ist wohl eher einen Compiler zu finden, der das unterstützt.
Wieso hat das ganze nichts mit Assembler zu tun? Alleine schon um in den RMode aus dem PMode zurück zu springen brauchst du Assembler, weil der Compiler weder das CR0 Register noch nen Sprung den du dafür brauchst kennt! Also brauchst du sehr wohl Assembler und willst du dann noch nen BIOS Interrupt aufrufen musst du bestimmte Register mit einem bestimmten Inhalt füllen (Assembler) und du musst den Interrupt aufrufen (Assembler).
Also Mode Wechsel sind immer mit Assembler verbunden (selbst wenn du es nur über Inline-Assembler machst, bleibt es Assembler)!
Edit::
Selbst in dem Patch den du ansprichst sieht man eindeutig das es über Assembler gelöst wurde, denn die Datei mit dem Code heißt trampoline.S, was eine Assemblerdatei ist. Man bekommt GCC dazu 16bit Code zu generieren (bzw. GAS) nur funktioniert das nicht so richtig.
-
Das ganze hat mit Assembler herzlich wenig zu tun. Das einzige Problem mit 16Bit und C/C++ ist wohl eher einen Compiler zu finden, der das unterstützt.
Wieso hat das ganze nichts mit Assembler zu tun? Alleine schon um in den RMode aus dem PMode zurück zu springen brauchst du Assembler, weil der Compiler weder das CR0 Register noch nen Sprung den du dafür brauchst kennt! Also brauchst du sehr wohl Assembler und willst du dann noch nen BIOS Interrupt aufrufen musst du bestimmte Register mit einem bestimmten Inhalt füllen (Assembler) und du musst den Interrupt aufrufen (Assembler).
Also Mode Wechsel sind immer mit Assembler verbunden (selbst wenn du es nur über Inline-Assembler machst, bleibt es Assembler)!
Die vorgehensweise beim Linken hat herzlich wenig mit Assembler zu tun (du hast ja m.E. auf die Frage zum Linken geantwortet).
Selbst in dem Patch den du ansprichst sieht man eindeutig das es über Assembler gelöst wurde, denn die Datei mit dem Code heißt trampoline.S, was eine Assemblerdatei ist. Man bekommt GCC dazu 16bit Code zu generieren (bzw. GAS) nur funktioniert das nicht so richtig.
Das Prinzip ist unabhängig von Assembler, zumindest wenn man gcc zum Setzen der Sektionsflags bekommt, was ich nicht nachgesehen habe, aber sehr wahrscheinlich möglich ist.
-
...(du hast ja m.E. auf die Frage zum Linken geantwortet).
Auch. Aber eigentlich mehr wie du es hinbekommst ohne dich verrenken zu müssen. Das wichtigste und schwierigste ist halt in den RMode und wieder zurück in den PMode zu kommen. Wie man den Code dann in eine Objektdatei bekommt ist relativ einfach (und ich finde weiterhin am einfachsten, wenn man es über eine Assemblerobjektdatei löst, aber jedem das Seine).
Das eigentlich größte Problem (vorallem am Linken) ist, dass man keine Symbole benutzen darf (die vom Linker aufgelöst werden müssen), während man 16bit Code schreibt, denn das Mixen von 16bit und 32bit Offsets kann der Linker nicht (ich habs probiert ;) ).
@bluecode
Ich denke mal wir haben aneinander vorbei geredet. Du meinst das Linken und ich wie man den Code schreibt.
-
Das eigentlich größte Problem (vorallem am Linken) ist, dass man keine Symbole benutzen darf (die vom Linker aufgelöst werden müssen), während man 16bit Code schreibt, denn das Mixen von 16bit und 32bit Offsets kann der Linker nicht (ich habs probiert ;) ).
FreakyPenguin hat es offensichtlich auch probiert (für seinen SMP-Code) und es muss wohl funktioniert haben.
-
FreakyPenguin hat es offensichtlich auch probiert (für seinen SMP-Code) und es muss wohl funktioniert haben.
Ohne diesen Code gesehen zu haben sage ich mal nein. Du hast mich wahrscheinlich falsch verstanden.
Du kannst wunderbar Labels definieren und diese dann woanders benutzen, aber was du nicht kannst ist, Label innerhalb des 16bit Codes benutzen, die der Linker auflösen muss, dann bekommst du irgendeine Fehlermeldung von wegen das er bei 32bit ELF keine 16bit Offset auflösen kann.
Ich meine konkret:
RMode:
;16bit Code Anfang
code
call FOO
code
;16bit Code Ende
RModeEnd:
Irgendwo in deinem C Code kannst du "RMode" und "RModeEnd" benutzen, aber er Linker kann die externe Adresse von "FOO" nicht auflösen, da er 16Bit Adressen/Offsets in einer 32bit ELF Datei nicht kann/will.
-
In meinem Code referenziere ich im 32-Bit Code auch keine 16-Bit symbole. Brauche ich ja auch nicht. Die Funktion kann in eine eigene Section, und dann kann mir der linker dafür ein 32-Bit Symbol geben, und gut ist.
Edit: Wobei ich da natürlich keine Funktionsaufrufe mit Moduswechsel habe da.
-
kann man auch ohne asm mov CR0,xxxxxxx0 schreiben? ;)
-
Ich kenne keine Sprache, die dich ohne Inline-Assembler auf die Steuerregister zugreifen lässt, wenn du das meinst.