Fast-Dfree (Assembler)

Jeder kennt bei Harddisks das Problem, den freien Speicherplatz zv ermitteln. Das GEMDOS stellt zwar eine Funktion dafür zur Verfügung, aber bei einer SH205 mit 4 Partitionen dauert das für alle zusammen schon mal 20 Sekunden. Mit diesem kleinen Programm im AUTO-Ordner, das im Speicher nicht mal 500 Bytes belegt, ist die Dfree-Funktion des GEMDOS 14 (!!!)mal schneller als vorher, D.H. die gesamten freien Cluster der Harddisk hat man in ca. 1,4 Sekunden!

Diese kleine Routine ersetzt die Dfree-Funktion des GEMDOS vollständig. Nur bei Disketten (12-Bit-FAT) wird die (dort hinreichend schnelle) Originalroutine genutzt. Man kann die Routine auch sehr schön in eine Command-Shell implementieren, welche (wenn an IBM angelehnt) bei jedem DIR die freie Kapazität der Datenträgers ausgibt. Auch selbstprogrammierte File-Selektoren mit Laufwerksinfo profitieren von dieser Routine.

Besonderer Dank gilt an dieser Stelle Thomas Quester, der mich erst auf die Idee gebracht hat, eine solche Routine zu schreiben.

Das Programm ist zwar dokumentiert, aber hier noch einmal eine grobe Beschreibung der Vorgehensweise von Fast-Dfree():

  1. Bios-Parameter-Block des entsprechenden Laufwerks anfordern
  2. bei 12-Bit-FAT in die Originalroutine ->
  3. sonst die Gesamt-Cluster-Anzahl merken sowie den Startsektor der 2.FAT
  4. 2 Sektoren der FAT einlesen (der Buffer ist gerade 1k groß).
  5. Beim ersten Aufruf werden die ersten 3 Cluster nicht mitgezählt, da Sie vom GEMDOS aus nur intern verwandt werden.
  6. Alle Words, welche gleich 0 sind, werden gezählt (16-Bit-FAT!).
  7. Dabei wird die Gesamt-Cluster-Anzahl heruntergezählt,
  8. wenn 512 Cluster gezählt wurden und die Gesamt-Cluster-Anzahl>0 ist, nach 4
  9. Das war’s.

Da das Programm mit dem OMIKRON.Assembler (Version 1.52) erstellt wurde, ist es gut möglich, daß andere Assembler z.B. den Pseudo-Opcode OUTPUT nicht kennen. Diesen kann man einfach weglassen. Ebenso ist mit der Adressierungsart Absolut-Short zu verfahren, welche beim OMIKRON.Assembler durch ein .w hinter dem Operator erzwungen werden kann.

;================================================
;= Fast-Dfree() - beschleunigt die Dfree-       =
;= Funktion des Gemdos bei 16-Bit-FATS          =
;= bei einer SH205 um Faktor 14 !!!             =
;= Auf dem Desktop wird das Info 3mal schneller = 
;= Die neue Dfree-Funktion wird ins GEMDOS      =
;= eingesetzt und ersetzt bei                   =
;= 16-Bit-FATS (Harddisk, Ramdisk, etc.) die    =
;= originale Dfree-Routine vollständig!         =
;=                                              =
;= Nach einer Idee von Thomas Quester (Danke)   =
;=                                              =
;= Enwtwickelt von Markus Fritze                =
;= (c) MAXON Computer GmbH 1990                 =
;================================================
                OUTPUT 'DFREE' ;bei andernen Assemblern evtl.weglassen

anfang:         bra     init

;================================================
;= Der neue Gemdos-Vektor                       =
;================================================

                DC.B    'XBRA'      ;XBRA-Standard f.vektorverbgnde Programme 
                DC.B    'XDFR'      ;Kennung von X-soft, Unterkennung: DFREE
old_vektor:     DS.L    1
new_gemdos:     move    USP,A0
                btst    #5,(SP)     ;Aufruf aus dem User-Mode? 
                beq.s   new_gemdos1 ;Ja!
                movea.l SP,A0 
                addq.l  #6, A0

new_gemdos1:    cmpi.w  #$36,(A0)   ;Dfree()
                beq.s   dfree       ;eigene Routine testen

new_gemdos_exit:movea.l old_vektor(PC),A0
                jmp     (A0)        ;Originale GEMDOS-Routine

;================================================
;= Bei einer 12-Bit-FAT (Disketten) ist die     =
;= interne Routine schnell genug.               =
;= Deswegen haben ich mir die Arbeit gespart.   =
;================================================

dfree_12bit_fat:movem.l (SP)+,D1-A6
                bra.s   new_gemdos_exit ;Originalroutine aufrufen

;================================================
;= Die neue Dfree()-Funktion für 16-Bit-FATs    =
;= Es werden einfach alle Null-Words in der     =
;= 2.FAT gezählt, das ist alles.                =
;= Zu beachten ist lediglich, daP die ersten 3  =
;= Words nicht mitgezählt werden!               =
;================================================

dfree:          movem.l D1-A6,-(SP)
                movea.l 2(A0),A4        ;Bufferadr 
                lea     12(A4),A4       ;für Predecrement (s.u.)

                move.w  6(A0),D7        ;Drive 
                subq.w  #1,D7
                bpi.s   dfree3          ;aktuelles LW?

                move.w  #$19,-(SP)
                trap    #1              ;Dgetdrv()
                addq.l  #2, SP
                move.w  D0,D7           ;aktuelles LW

dfree3:         cmp.w   #1,D7           ;Disk?
                ble.s   dfree_12bit_fat ;dann GEMDOS-Dfree()
;Wenn obige Abfrage fehlt, wird nach dem Formatieren einer einseitigen Disk 
;von eine 16-Bit-FAT ausgegangen (fehlendes Media-Change)

                move.w  D7,-(SP)        ;drive 
                move.w  #7,-(SP)
                trap    #13             ;Getbpb (drive)
                addq.l  #4,SP
                tst.l   D0
                bmi.s   dfree_error     ;Gerät nicht da, Fehler 
                movea.l D0,A6           ;Adresse merken

                btst    #0,17(A6)       ;Flagsb testen nach 16 oder 12-Bit-FAT 
                beq.s   dfree_12bit_fat ;12-Bit-FAT =>Original ist schnell genug

                move.w  10(A6),D6       ;fatrec - Startsektor der 2.FAT

                moveq   #0,D5 
                move.w  2(A6),D5
                move.l  D5,(A4)         ;Sektoren pro Cluster einsetzen

                move.w  (A6),D5
                move.l  D5,-(A4)        ;Bytes pro Sektor einsetzen

                move.w  14(A6),D5       ;numcl - Gesamtanzahl der Cluster merken 
                move.l  D5,-(A4)        ;und einsetzen

                moveq   #0,D4           ;Anzahl der freien Cluster=0 
                moveq   #0,D3           ;Flag für den Startsektor der FAT löschen 
dfree0:         movea.l $04C6.w,A5      ;Bufferadresse holen (__dskbuf) 
                move.w  D7,-(SP)        ;Drive 
                move.w  D6,-(SP)        ;fatrec
                move.w  #2,-(SP)        ;2 Sektoren einlesen
                move.l  A5,-(SP)        ;Buffer für die Sektoren
                clr.w   -(SP)           ;normales Lesen
                move.w  #4,-(SP) 
                trap    #13             ;Rwabs()
                lea     14(SP),SP
                tst.l   D0 
                bmi.s   dfree_error     ;Lesefehler, Fehlermeldung zurückgeben

                addq.w  #2,D6           ;fatrec+2

                move.w  #$01FF,D0       ;512 Cluster pro 2 Sektoren der FAT

                tas.b   D3              ;1.Sektor mit den ersten drei Clustern? 
                bne.s   dfree1          ;Nein! =>

                addq.l  #6,A5           ;die ersten der Cluster werden 
                subq.w  #3,D0           ;nicht mitgezählt! 
                subq.w  #3,D5           ;3 Cluster bereits abziehen

dfree1:         tst.w   (A5)+           ;freien CLuster gefunden? 
                bne.s   dfree2          ;Nein! =>
                addq.w  #1,D4           ;einen freien Cluster gefunden 
dfree2:         subq.w  #1,D5           ;numcl-1
                dbeq    D0,dfree1
                bne.s   dfree0          ;Ende noch nicht erreicht, weiter geht's

                move.l  D4,-(A4)        ;Anzahl der freien Cluster einsetzen 
                moveq   #0,D0           ;alles ok, kein Fehler

dfree_error:    movem.l (SP)+,D1-A6
                rte                     ;Das war’s schon

init:           pea     new_gemdos(PC)
                move.l  #$050021,-(SP)
                trap    #13             ;Setexc (33,new_gemdos)
                addq.l  #8, SP
                move.l  D0,old_vektor   ;Original-Vektor merken

                pea     init_text(PC)
                move.w  #9,-(SP)
                trap    #1              ;eine Meldung am Anfang
                addq.l  #6,SP

                clr.w   -(SP)           ;Kein Fehler aufgetreten 
                pea     init-anfang+$0100.w ;residentes Programm <500 Byte 
                move.w  #$31,-(SP)
                trap    #1              ;Ptermres()

                DATA
init_text:      DC.B    'Fast-Dfree', 13,10
                DC.B    '(c) 1990 MAXON Computer GmbH, von Markus Fritze',13,10,0
                END 


Markus Fritze
Aus: ST-Computer 03 / 1990, Seite 84

Links

Copyright-Bestimmungen: siehe Über diese Seite