Virenprogrammierkurs
Nach einem Sommermonat langen Wartens ist er nun endlich da: Der 4 . Teil des Virenprogrammierkurses!
Heute geht es wieder um das komplexe Thema der Fortpflanzung beim Laden.
Wie schon im letzten Teil erwähnt fehlt uns nur noch
der Rest der LOAD-Vermehrung und noch eine kleine
Routine, die am Anfang der Virus-Load- Routine steht.
Und um genau diese Routine geht es heute.
Sie erinnern sich: Wir hatten gesagt, daß wir alle
Befehle aus dem Betriebssystem übernehmen wollen, so
daß die ganz normale LOAD-Routine ausgeführt wird, mit dem Unterschied, daß sich unser Virus dann hinzuschalten kann, wann ER möchte! Dies muß er schon
gleich am Anfang tun, nämlich dort, wo über den Vektor in die LOAD-Routine eingesprungen wird, und zwar, um sich den Filenamen des Programms zu merken, daß
geladen werden soll. Dieser wird normalerweise ja
schon von Basic irgendwo im Speicher abgelegt.
Anschließend übergibt BASIC der LOAD-Routine die Adresse und Länge des Filenamens mit Hilfe der SETNAM-Routine. Diese steht im Betriebssystem bei $ FFBD und wird folgendermaßen aufgerufen:
X-Register: LO-Byte der Adresse des Filenamens Y-Register: HI-Byte der Adresse des Filenamens Akku : Länge des Filenamens
Zum besseren Verständnis hier ein Beispiel:
8000 LDA #$04 8002 LDX #$0A 8004 LDY #$80 8006 JSR $FFBD 8009 RTS 800A .TX "NAME"
Es werden also die Adresse des Filenamens ( hier:
$800 A) und die Länge des Filenamens ( hier 4) übergeben.
Die Routine SETNAM macht nun nichts anderes, als
diese Werte, die ja nachher beim Laden wichtig sind, in drei Speicherzellen in der Zeropage zwischenzuspeichern. Diese Speicherzellen sind $ BB und $ BC für
die Namensparameter. In Speicherzelle $ B7 wird die
Länge des Namens zwischengespeichert. Leider bleiben
diese Werte dort nicht bis in alle Ewigkeiten stehen.
Sie gehen im Laufe der LOAD-Routine verloren, da
diese Speicherzellen noch anderweitig verwendet werden. Der Filename z. B. wird vom Betriebssystem an das
Ende des normalen Basic-Arbeitsspeichers gelegt. Und
dort ist er leider nicht genug geschützt. Ein langes
Programm überschreibt ihn einfach beim Laden. Wir
müssen uns diese Werte und den Filenamen also
" merken", bevor wir die LOAD-Routine auf diese
Bereiche loslassen.
Und genau das tut unsere kleine Routine von Zeile
1020 bis 1130 . Wie immer folgt nun eine kleine Dokumentation, die Ihnen die Funktion der Routine erläutern soll:
1020 -LOAD PHA ;Akku retten 1030 - LDA FILELO ;LO-Adresse des 1040 - STA $FB ;Namens setzen 1050 - LDA FILEHI ;HI-Adresse des 1060 - STA $FC ;Namens setzen 1070 - LDY FILELENG ;Länge des Namens 1080 - STY LENGNAM ;setzen 1090 -LOOP2 LDA ($FB),Y ;Name kopieren 1100 - STA NAMEBUFF+2,Y 1110 - DEY ;Zähler vermindern 1120 - BPL LOOP2 ;Fertig? 1130 - PLA ;Akku zurückholen
In Zeile 1020 wird erst einmal der Akku auf den Stapel geschoben, da wir seinen Inhalt später wieder
brauchen. Um dies verständlich zu machen, muß man zuerst einmal wissen, welche Parameter die LOAD-Routine
beim Aufruf benötigt.
Ähnlich wie bei der SAVE-Routine müssen der LOAD-Rou- tine zuerst Filename, Filenummer, Geräteund Sekundäradresse des zu ladenden Files übergeben werden.
Dies geschieht, wie schon bei der SAVE-Routine, durch
die Betriebssystemroutinen SETPAR ($ FFBA) und SETNAM
($ FFBD), welche wir ja schon beschrieben hatten. Anschließend kann erst die LOAD-Routine aufgerufen werden, und zwar mit den folgenden Parametern:
Xund Y-Register enthalten die Startadresse des Programms, das geladen werden soll.
Der Akku dient als LOAD/ VERIFY-Flag.
Wie wir ja vom letzten Teil des Kurses noch wissen, werden die Werte aus X und Y schon von der " Vorroutine" des Betriebssystems bei $ F49 E zwischengespeichert, so daß deren Inhalt unwichtig wird und wir somit diese Register verwenden dürfen. Nur im Akku
steht noch eine Information, die ebenfalls nicht verloren gehen darf, aber erst später vom Betriebssystem
zwischengespeichert wird. Im Akku steht nämlich eine
Information, die dem Betriebssystem sagt, ob ein LOAD
oder nur ein VERIFY erfolgen soll.
Steht im Akku eine 0, so wird ein Programm ordnungsgemäß geladen. Bei einer 1 allerdings wird nur das
Programm auf der Diskette mit dem derzeitigen Speicherinhalt verglichen, eben die VERIFY-Funktion ausgeführt. Logischerweise müssen wir also den Akku erst
einmal auf den Speicher retten.
Weiter nun mit unserer Routine ab Zeile 1020 :
Nachdem nun der Akku endlich benutzbar wurde, werden
als Erstes die Zwischenspeicherbytes der Adresse des
Filenamens in die Adressen $ FB und $ FC umkopiert.
Diese beiden Adressen befinden sich, wie Sie ja sehen
( es werden nur 8 Bit benutzt), auch in der Zeropage.
Sie sind zusammen mit den zwei folgenden Bytes $ FD
und $ FE eine der Ausnahmen, die nicht vom Betriebssystem benutzt werden, sondern dem Assemblerprogrammierer zur freien Verfügung stehen.
Wir wollen mit Hilfe der indirektindizierten Adressierung den Filenamen auslesen.
Dies geschieht über einen Zeiger, den wir soeben
durch unsere " Umkopiererei" ins Leben gerufen haben.
Vorher sichern wir aber zuerst noch die Länge des
Filenamens in einem Variablenbyte ( LENGNAM) . Dieses
wurde im Assemblerquelltext definiert, und zwar als
6 . Byte vor Beginn des Programms, ähnlich wie bei
einigen weiteren Laufvariablen, die hauptsächlich von
dem Gag-Programm am Ende verwendet werden. Übrigens:
Die Namen FILELO, FILEHI und FILELENG sind Konstanten
und ebenfalls am Anfang des Quelltextes definiert.
Sie stehen für die Zwischenspeicherbytes des Filenamens.
Anschließend wird nun der Filename umkopiert. Einen
Zähler für die Länge des Filenamens haben wir ja noch
vom Umkopieren im Y-Register stehen. Also brauchen
wir immer nur einen Wert herunterzuzählen und zu prüfen, ob schon alle Bytes kopiert wurden. NAMEBUF ist
übrigens auch ein Label für einen Speicher, diesmal
am Ende des Quellistings, in dem 16 Bytes ( so lang
darf der Filename maximal sein) für den Filenamen
Platz sind.
Warum in diese Adresse "+2" gespeichert werden muß
und nicht gleich an die Adresse NAMEBUF, wird später
noch erklärt.
Jetzt wird erst der Akkuinhalt wieder vom Stack
geholt und weiter geht' s mit den Betriebssystemroutinen.
Hiermit wären wir auch gleichzeitig am Ende dieses
Kursteils angekommen. Nächsten Monat wollen wir dann
die Fortpflanzung endlich ganz abhaken.
Bis dahin wünschen wir Ihnen jedenfalls viel Spaß
beim Virenzüchten.