dos prog resident machen



  • Hallo,

    hab zwar die Suche schon bemüht, aber des spuckt mir irgendwie nix brauchbares aus:

    Ich würd mir gerne unter DOS eine kleine Interrupt-Routine selber schreiben.
    Funkt soweit auch ganz ordentlich, nur:
    wie sag ich dem dummen Dos jetzt, dass es es das Prog auch im Speicher hält?
    Dürfte wohl irgendwie über Dosfunktion 31h laufen.

    Aus der Doku:

    Eingabe AH = 31h
    AL = Ende-Code
    DX = Anzahl der zu reservierenden Paragraphen
    Ausgabe keine
    .
    .
    .
    Die Anzahl der zu reservierenden Paragraphen (jeweils 16 Byte) gibt an, wie viele Byte, beginnend mit dem PSP, nicht mehr zur weiteren Verwendung freigegeben werden dürfen.

    Aber was um alles in der Welt sind Paragraphen, und PSP is mir auch ned so wirklich geläufig???

    Irgendwo hab ich noch gelesen, dass des ganze über eine *.com - Datei laufen muss??

    danke
    Martin



  • Hi.

    1 Paragraph ist (wie in deinem Text richtig steht) 16Byte. Sollte doch eigentlich eindeutig sein. 😕

    Das PSP ist das Program Segment Prefix. Das ist ein 100h Byte langer Speicherbereich, den DOS bei .exe-Dateien vor dem ersten Segment des Programms und bei .com-Dateien im Programmsegment selbst reserviert, um darin Informationen ueber geoeffnete Datei-Handler, die Menge des vom Programm reservierten Speichers etc. zu sichern.

    Das ganze muss IMHO nicht ueber eine .com-Datei laufen. Du musst nur darauf achten, wie du deine Programmsegmente anordnest. Das Segment mit dem Interrupt Handler sollte also moeglichst direkt hinter dem PSP liegen, um moeglichst wenig Speicher zu blockieren.



  • Hi,
    Danke erst mal.

    Also soweit ich des etz verstanden hab, muss in DX praktisch ein Wert größer 100h stehen?
    Aber wie krieg ich den dann raus?
    Hab jetzt einfach mal willkürlich einen gesetzt, aber funktioniert leider ned so ganz.
    Vielleicht mal a bissl Code:

    include ./intMacro.asm
    
    assume cs:code
    
    code segment
    
    int00 proc far  ; neue Interrupt-Routine, gibt nur X aus
    sti
        mov dl,'X'
        mov ah,2
        int 21h
    iret
    endp
    
    start:
    
        mov ax,offset int00
        setVector code,ax,0 ; setzt den neuen Int-Vektor
    
        int 0 ; prüfen, ob neuer Vektor korrekt
    
        mov ah,31h
        mov al,0
        mov dx,110h ; WELCHER WERT MUSS HIER REIN???
    
        int 21h
    
    code ends
    	end start
    

    Würde soweit auch funktionieren.

    Aber: wenn ich jetzt ein anderes Prog starte, das einfach nur einen "int 0" ausführt, wird das 'X' aus der neuen Routine noch ausgegeben und dann hängt sich
    der PC auf 😞

    mfg
    Martin

    PS:
    zumindest in der Vorschau steht jetzt "assume cs:;code" und "mov dl,';X'".
    hab aber cs:code und dl,'X' 😕



  • anonymus schrieb:

    Also soweit ich des etz verstanden hab, muss in DX praktisch ein Wert größer 100h stehen?

    =>

    DX = Anzahl der zu reservierenden Paragraphen

    Nochmal: 1 Paragraph != 1 Byte

    Immerhin hast du insofern recht, als dass mindestend 100h Byte fuer das PSP reserviert werden muessten (Das sind 10h Paragraphen).
    Das Minimum liegt aber in DOS sinnvollerweise bei 11h (also 110h Byte), da ein PSP allein eigentlich keinen Sinn macht. 😉

    Du solltest uebrigens keinen Interrupt unter 40h mit deinem Code belegen, da die Interrupts mit niedrigerer Nummer eigentlich schon alle mit einer Funktion belegt sind.
    Int 0 ist zB. der Handler fuer Exception 0 (Division durch 0).
    Der Fehler in deinem Code koennte nun zB. daher kommen, dass du in deinem Int-Handler die Register nicht sicherst. dx und ax werden veraendert, wenn dein Interrupt aufgerufen wird. Das "far" bei der Declaration solltest du vielleicht auch weglassen (ist hier schliesslich nicht ganz richtig).

    anonymus schrieb:

    Aber wie krieg ich den dann raus?

    Entweder du schaetzt ab, wie gross dein Code wohl sein mag (in deinem Fall wohl kaum groesser als 1 Parahgraph) oder du laesst die Groesse deines Codes vom Assembler berechnen. zB. indem du die Differenz zwischen zwei Labels bestimmst.

    Beispiel:

    int00 proc  ; neue Interrupt-Routine, gibt nur X aus 
    sti 
        mov dl,'X' 
        mov ah,2 
        int 21h 
    iret 
    endp 
    
    start:
    ...
    mov dx, (offset start - offset int00 + 110h) / 16 ;+110h ist das Minimum; /16 wegen Umrechnung auf Paragraphen
    

    anonymus schrieb:

    PS:
    zumindest in der Vorschau steht jetzt "assume cs:;code" und "mov dl,';X'".
    hab aber cs:code und dl,'X'

    Das ist ein Fehler in der Forumssoftware. 😉



  • argh

    Bloss gut, dass Dummheit ned weh tut:
    Hab im Test-Programm vergessen, dieses zu Beenden.
    Kann dann natürlich ned funktionieren.
    Zumindes in "Dosbox" und in der XP-Dosbox funzt des ganze etz.
    Normales Dos werd ich gleich testen.

    Bloss eins noch:
    Wenn ich in der Interruptroutine Register Sichern will,
    wo muss ich da den Stack definieren?
    weil einfach so pushen, geht vermutlich ins Auge.
    Kann ich einfach wie gewohnt ein Stacksegemt aufmachen?

    nochmal Danke
    Martin

    PS: int 0 war hier einfach mal zum Ausprobieren. Is Klar, dass ich da ned einfach irgendwas durch Sinnloses Zeug ersetzten sollte 😉



  • Den Stack stellt normalerweise das Programm bereit, von dem die Interruptroutine aufgerufen wird. Von daher brauchst du dich nicht weiter um den Stack kuemmern.
    Kannst einfach so sofort drauf zugreifen. 🙂



  • Den Stack stellt normalerweise das Programm bereit, von dem die Interruptroutine aufgerufen wird

    Des wird ein Problem:
    Ich hab vor, den IRQ 7 (int 0fh, parallele Schnittstelle) zu überschreiben.
    => Wenn von da ein Interrupt kommt, muss ned unbedingt ein Programm laufen, des
    auch einen Stack definiert hat.

    Ich versuchs etz einfach mal mit

    stapel segment STACK 'STACK'
    db 16 dup(0)
    stapel ends
    

    zwischen "endp" und "start:".
    Wird schon schief gehn 😉



  • Sobald der POST erfolgreich beendet wurde, kannst du davon ausgehen, dass immer ein Programm ablaeuft. Folglich sollte eigentlich (vor allem in einem funktionierenden OS) immer ein Stack eingerichtet sein.
    Aber wie du es nun handhabst ist letzendlich reichlich egal.
    Bleibt nur eine Sache zu bedenken 😉 :
    Bevor du die Adresse des Stacks (ss:esp) in deinem Interrupt handler veraenderst, musst du die alte Adresse sichern!


Anmelden zum Antworten