Autor Thema: call im RM in variables Segment  (Gelesen 7170 mal)

RedEagle

  • Beiträge: 244
    • Profil anzeigen
    • RedEagle-OperatingSystem - Projekt
Gespeichert
« 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
« Letzte Änderung: 29. April 2010, 13:55 von RedEagle »

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 29. April 2010, 13:59 »
Hi,

Segment auf den Stack legen, Offset auf den Stack legen und retf ausführen.
Dieser Text wird unter jedem Beitrag angezeigt.

RedEagle

  • Beiträge: 244
    • Profil anzeigen
    • RedEagle-OperatingSystem - Projekt
Gespeichert
« Antwort #2 am: 29. April 2010, 14:04 »
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:

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 29. April 2010, 14:21 »
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
« Letzte Änderung: 29. April 2010, 14:28 von PorkChicken »
Dieser Text wird unter jedem Beitrag angezeigt.

RedEagle

  • Beiträge: 244
    • Profil anzeigen
    • RedEagle-OperatingSystem - Projekt
Gespeichert
« Antwort #4 am: 29. April 2010, 15:05 »
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

 

Einloggen