Lowlevel
Lowlevel => Softwareentwicklung => Thema gestartet von: RedEagle am 29. April 2010, 13:53
-
Hi
Ich erweitre gerade den Skrip-Interpreter meines Bootloaders und möchte gerne das Feature einbauen ein Segment, in welches vorher Daten geladen wurden, auszuführen.
Beispiel:
ld /reos/reos16.knl 3000
exec 3000
Die Datei reos16.knl wird in das Segment 0x3000 geladen, und soll anschließend ausgeführt werden
Bisher war das Ausführen hart im Code des Bootloaders - nach der Ausführung des Skriptes wurde call 0x3000:0x0000 ausgeführt.
Das würde allerdings in einem Chaos enden, falls jemand im Skript den Kernel in ein anderes Segment lädt.
Ein weiterer Nachteil ist, das nach dem Laden das Skript beendet werden muss, damit der call kommt. Beim runterfahren - also wenn der Kernel wieder verlassen wird, muss nun ein 2. Skript ausgeführt werden anstatt das 1. Skript nach einem exec weiter auszuführen.
Daher die Frage:
Wie kann ich in ein beliebiges Segment springen?
So sieht die Exec-Funktion aus:
[global _ExecSegment]
_ExecSegment:
push bp
mov bp, sp
push si
push di
push ds
push es
mov ax, [bp+4]
mov ds, ax
; call
pop es
pop ds
pop di
pop si
pop bp
ret
[bp+4] ist das Segment
-
Hi,
Segment auf den Stack legen, Offset auf den Stack legen und retf ausführen.
-
Allerdings muss ich ja dann auch meinen aktuellen ip und das aktuelle Segment auf den Stack legen damit anschließend der Rücksprung funktioniert.
Ich habe gehofft dass es da eine elegantere Lösung gibt :cry:
-
Du kannst auch das Segment und Offset in einer Variable speichern und dann einen indirekten far-call machen.
Ansonsten müsste auch folgende Sequenz funktionieren:
; ...
mov ax, [bp+4]
mov ds, ax
call far go_kernel
; der kernel landet mit einem retf wieder hier
; ...
go_kernel:
push segment
push offset
retf ; spring in den kernel
-
Super - Funktioniert und ist sogar relativ sauber :)
wobei der far-call probleme mit dem as86-format machte - habe es dann wie folgt gelöst:
push cs
call go_kernel
Die fertige Funktion:
[global _ExecSegment]
_ExecSegment:
push bp
mov bp, sp
push si
push di
push ds
push es
mov ax, [bp+4]
mov ds, ax
push cs
call FarExec ; Segment //ax// ausführen
pop es
pop ds
pop di
pop si
pop bp
ret
FarExec:
push ax
push word 0x0000
retf ; spring in den kernel