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 aufmfg
MartinPS:
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
MartinPS: 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!