8086 Assembler (MS-DOS):
Schneller Verzeichniswechsel mit GO

Unter MS-DOS bewegt man sich mit dem Befehl „CD” durch die Verzeichnisse. Das hier gezeigte Programm „GO” erleichtert die dabei anfallende Tipparbeit. Dazu enthält es einige Ziele des Verzeichnisbaumes. Wird es ohne Parameter aufgerufen, zeigt es die von ihm unterstützten Ziele (siehe blauen Kasten unterhalb). Tippt man jedoch „go etc”, findet man sich im Verzeichnis C:\WINDOWS\SYSTEM32\DRIVERS\ETC wieder.
D:\dos\ML\Test>go
Usage: GO pfad
Als pfad wird ein Pfadname, Teile eines Pfadnamens,/ oder \ oder .. erwartet.
Die aktuell auf der Platte vorhandene Directory-Struktur laesst sich mit
tree /A >datei.txt
speichern.

Directories:
D:\DATEN       D:\DATEN\123    D:\DATEN\ADMI   D:\DATEN\WORD
D:\DOS         D:\4DOS         D:\TEMP         D:\TEMP\FREDDY-DATEIEN
C:\WINDOWS     C:\WINDOWS\SYSTEM32             C:\WINDOWS\SYSTEM32\DRIVERS\ETC
D:\TEMP\ASM\HOMEPAGE NEW       D:\HOMEPAGE     D:\HOMEPAGE\NETCUP\HTML
D:\DOS\MASM    D:\DOS\ML\TEST  D:\DOS\ML\QUELLEN               D:\DOS\NU
D:\DOS\Q       D:\DOS\QB45     D:\DOS\QB45\BEISPIEL
D:\DOS\QB45\RATG_BSP           D:\DOS\TURBOC   D:\DOS\TURBOC\INCLUDE
D:\DOS\TURBOC\LIB              D:\INSTALL      D:\GI
D:\dos\ML\Test>

Die Funktionsweise wird anhand einiger Beispiel deutlich:

  • go 1 wechselt auf D:\DATEN\123
  • go 32 wechselt auf C:\WINDOWS\SYSTEM32
  • go etc wechselt auf C:\WINDOWS\SYSTEM32\DRIVERS\ETC
  • go l/t, go l\t, go ml, go est oder go test wechselt auf D:\DOS\ML\TEST
  • go new wechsel auf D:\TEMP\ASM\HOMEPAGE NEW

Obwohl das Programm die Routinensammlung firm.mac verwendet, besitzt es eine eigene Routine zur Wandlung des eingetippten Parameters in Großschrift. Die Indexregisterbenutzung bei dem entsprechenden Unterprogramm in firm.mac war hier unpassend.

Die ab dem Merkmal „names” definierte Tabelle der unterstützten Verzeichnisse muss individuell aufgebaut werden.

Das aufgelistete Programm verarbeitet lange Verzeichnisnamen. Diese dürfen auch Zwischenräume (blanks) enthalten.

Es ist grundsätzlich möglich, das Programm für das MODEL SMALL abzuändern. Es wird dabei an einigen Stellen komplizierter, da man sich mit dann zwei getrennt anzusprechenden Segementregistern beschäftigen muss. Es sind die Segmentregister ES für die Auswertung der beim Programmaufruf mitgegebenen Parameter und DS für das DATA-Segment. Bei Verwendeung des MODELs TINY entfällt diese Problematik.


.MODEL TINY
title   go fuer HP-Laptop
        page    65,120
comment #
zur schnellen Anwahl von Directories
Matthaei, 12.11.90, 27.12.93, 26.10.200
23.1.2011 angepasst fuer ML
12.2.2011 lange Directorynamen und Suchfunktion erweitert
#
title   entab
        page    65,120

false   equ     0
true    equ     not false

dump$   equ     false   ;fuer mdump, rdump
prompt$ equ     false   ;fuer enter, inkjn
intasc$ equ     false   ;fuer int2asc, asc2int
string$ equ     true    ;fuer fill, cmpstr, lenstr, instrg, movstr, ucaseg, lcaseg

.CODE

        org     100h

_start: jmp     around
        include firm.mac

;Arbeitsfelder
wlparm dw       0       ;Nettoparameterlaenge

wparm   dw      0       ;Startadr (Offset) des Parameters
wlname  dw      0       ;Laenge des Eintrages in Namenstabelle
wname   dw      0       ;Startadresse (Offset) des Eintrages in Namenstabelle
curdir  db      130 dup ('0')   ;Zwischenspeicher Name des aktuellen Verzeichnisses

spaces15 db     '               ',0     ;15 Spaces zur Anzeige

;Besondere Directories
home    db      '\',0   ;Grundbibliothek
back    db      '..',0  ;eine Stufe zurück

;Tabelle der Directorynamen
;Bitte alles in Grossschrift!!!
names:
  dbz "D:\DATEN"
  dbz "D:\DATEN\123"
  dbz "D:\DATEN\ADMI"
  dbz "D:\DATEN\WORD"
  dbz "D:\DOS"
  dbz "D:\4DOS"
  dbz "D:\TEMP"
  dbz "D:\TEMP\FREDDY-DATEIEN"
  dbz "C:\WINDOWS"
  dbz "C:\WINDOWS\SYSTEM32"
  dbz "C:\WINDOWS\SYSTEM32\DRIVERS\ETC"
  dbz "D:\TEMP\ASM\HOMEPAGE NEW"
  dbz "D:\HOMEPAGE"
  dbz "D:\HOMEPAGE\NETCUP\HTML"
  dbz "D:\DOS\MASM"
  dbz "D:\DOS\ML\TEST"
  dbz "D:\DOS\ML\QUELLEN"
  dbz "D:\DOS\NU"
  dbz "D:\DOS\Q"
  dbz "D:\DOS\QB45"
  dbz "D:\DOS\QB45\BEISPIEL"
  dbz "D:\DOS\QB45\RATG_BSP"
  dbz "D:\DOS\TURBOC"
  dbz "D:\DOS\TURBOC\INCLUDE"
  dbz "D:\DOS\TURBOC\LIB"
  dbz "D:\INSTALL"
  dbz "D:\GI"
  db 0

;-------
;Upros
;-------
;------
;rcut ermittelt das Ende des Tokens anhand der Separatoren
;CR oder 00. Die Stringlaenge wird in CX zurückgegeben.
;Eingabeparameter: bx=Stringadresse
;------
rcut:   xor     cx,cx
        push    bx              ;der String wird über bx adressiert
        push    dx
        mov     dx,0d00h        ;Separaroren  cr und 00

rcut5:  cmp     b[bx],dl
        jz      rcut9
        cmp     b[bx],dh
        jz      rcut9
        inc     bx
        inc     cx
        jmps    rcut5

rcut9:  pop     dx
        pop     bx
        ret
;-------
;caseg string case conversions (german)
;Eingabeparameter: bx=Stringadresse, cx=Stringlaenge
;-------
Ucaseg1:
        or      cx,cx
        jz      luraus1 ;falls Leerstring

        push    bx              ;der String wird ueber bx adressiert
        push    cx
        push    dx
        mov     dx,6120h        ;DH = 'a', DL = conversion factor
convupper:
        mov     al,[bx]
        cmp     al,'/'
        jne     bu
        mov     [bx],b '\'
        jmps    luraus
bu:     cmp     al,dh
        jb      lu
        cmp     al,'z'
        ja      lu
        sub     al,dl
        mov     [bx],al
        jmps    luraus
lu:     cmp     al,'ä'
        jne     luoe
        mov     [bx],b 'Ä'      ;Ae
        jmps    luraus
luoe:   cmp     al,'ö'
        jne     luue
        mov     [bx],b 'Ö'      ;Oe
        jmps    luraus
luue:   cmp     al,'ü'
        jne     luraus
        mov     [bx],b 'Ü'      ;Ue

luraus: inc     bx
        loop    convupper

        pop     dx
        pop     cx
        pop     bx
luraus1: ret

;-------
;fbksl sucht im Token den naechsten ;Eingabeparameter: bx=Stringadresse
;Ausgabeparameter: bx=letzte Suchstelle
;Stringende: 0
;-------
fbksl:  cmp     b[bx],0
        je      fbksl9
        cmp     b[bx],'\'
        je      fbksl9
        inc     bx
        jmps    fbksl

fbksl9: ret

;-------
;Fortsetzung des Hauptpropgramms
;-------
around:
        mov     si,lparm        ;Laenge des Parameters
        xor     ch,ch
        mov     cl,[si]
        or      cx,cx
        jne     start2
        jmp     hilfe           ;Ausstieg, wenn keine Parameterangabe

start2: inc     si              ;ueüberlesen fueührende Spaces
        cmp     b[si],' '
        jne     start3
        loop    start2

;falls nur \ oder / eingegeben wurde, dann ins Grundverzeichnis
start3: cmp     b[si],'\'
        je      start4
        cmp     b[si],'/'
        jne     start5
start4: cmp     cx,1
        jne     start7
        lea     dx,home         ;CD mit \ auf Grunddirectory
        jmp     chg_dir

;falls nur .. eingegeben wurde, dann ins uebergeordnete Verzeichnis
start5: cmp     b[si],'.'
        jne     start10
        inc     si
        cmp     b[si],'.'
        jne     start10
        dec     si
        cmp     cx,2
        jne     start10
        lea     dx,back         ;CD mit .. eine Stufe zurueück
        jmp     chg_dir

;falls die Eingabe mit einem \ ode / beginnt, wird der \ oder / ignoriert
start7: inc     si
        dec     cx
start10:
        mov     bx,si           ;eingegebenen Parameter konditionieren,
        call    rcut            ;d.h., Laenge feststellen
        mov     w wlparm,cx     ;Nettolaenge des Parameters
        call    ucaseg1         ;und in Grossschrift sowie / in \  wandeln
        mov     w wparm,si      ;Startadresse des Parameters
        add     si,wlparm
        mov     b [si],0        ;eingegebenen Parameter mit 0 terminieren

;Hier beginnen die Vergleiche des Parameters
;1. Beste Aehnlichkeit versuchen: Parameter und Dirname voll identisch ?
        lea     di,names        ;Adresse der gespeicherten Directorynamen
        mov     bx,di
start12:
        call    rcut            ;cx enthaelt Laenge des Namenseintrages
        or      cx,cx
        jnz     start13
        jmp     start20         ;Namenstabelle ist abgearbeitet

start13:
        cmp     cx,w wlparm
        push    cx
        jnz     start18         ;verschieden lang

start15:                        ;cx=Laenge
        mov     si,bx           ;Adr. Eintrag in Namenstabelle
        mov     di,w wparm      ;Adresse Parameter
        cld                     ;Richtung aufwaerts
 repe   cmpsb
        jnz     start18         ;verschieden

        mov     di,bx           ;Eintrag in Namenstabelle fuer CD
        mov     dx,di
        jmp     chg_drv         ;CD mit passendem Namenseintrag

start18: pop    cx
        add     bx,cx           ;also verschieden, dann
        inc     bx              ;naechsten Namenseintrag aufsuchen
        jmps    start12

start20:
;2. Naechstbeste Aehnlichkeit versuchen: Parameter beginnt linksbüuendig
;   auf einem DIR- oder SubDIR- Namen
;   Der Vergleich erfolgt in der Laenge des Parameters
        mov     bx,offset names  ;Adresse der gespeicherten Directorynamen
start22:
        mov     w wname,bx      ;Adresse der Namenseintrages
        call    rcut            ;cx enthaelt Laenge des Namenseintrages
        mov     w wlname,cx
start23:
        call    rcut            ;cx enthaelt Laenge des Namenseintrages
        or      cx,cx
        jnz     start24
        jmp     start50         ;wenn Namenstabelle ohne Verzeichniswechsel
                                ;abgearbeitet ist

start24:
        cmp     cx,w wlparm
        jl      start38         ;Parameter ist laenger als Namenseintrag

start25:
        mov     cx,w wlparm
        mov     si,bx           ;Adr. Eintrag in Namenstabelle
        mov     di,w wparm      ;Adresse Parameter
        cld                     ;Richtung aufwaerts
 repe   cmpsb
        jnz     start30         ;verschieden

        mov     di,w wname      ;Eintrag in Namenstabelle fuer CD
        mov     dx,di
        jmp     chg_drv         ;CD mit passendem Namenseintrag

start30: call   fbksl           ;suchen, ob ein \ im Namenseintrag ist
        cmp     b[bx],'\'
        jne     start38         ;kein \ gefunden
        inc     bx              ;auf Namensanfang
        jmp    start23

start38:
        mov     cx,w wlname
        mov     bx,w wname
        add     bx,cx           ;naechsten Namenseintrag
        inc     bx
        jmp    start22

start50:
;3. Naechstsbeste Aehnlichkeit versuchen: Parameter beginnt irgendwo
;   innerhalb eines Namenseintrags.
;   Der Vergleich erfolgt in der Laenge des Parameters
        mov     bx,offset names  ;Adresse der gespeicherten Directorynamen
start52:
        mov     w wname,bx      ;Adresse der Namenseintrages
        call    rcut            ;cx enthaelt Laenge des Namenseintrages
        mov     w wlname,cx
start53:
        call    rcut            ;cx enthaelt Laenge des Namenseintrages
        or      cx,cx
        jnz     start54
        jmp     ret0            ;wenn Namenstabelle ohne Verzeichniswechsel
                                ;abgearbeitet ist

start54:
        cmp     cx,w wlparm
        jl      start68         ;Parameter ist laenger als Namenseintrag

start55:
        mov     di,w wname      ;Adr. Eintrag in Namenstabelle
        mov     si,w wparm      ;Adresse Parameter
        call    instrg          ;ist der Parmeter entgalten?
        jz      start68         ;nein. Dann naechster Namenseintrag

        mov     di,w wname      ;Eintrag in Namenstabelle fuer CD
        mov     dx,di
        jmp     chg_drv         ;CD mit passendem Namenseintrag

start68:
        mov     cx,w wlname
        mov     bx,w wname
        add     bx,cx           ;naechsten Namenseintrag
        inc     bx
        jmp    start52



;Drive und Verzeichnis wechseln
;CALL interrupt(H21, inreg, outreg)
chg_drv:
        push    dx
        mov     dl,[di] ;Drive Buchstabe
        and     dl,1fh  ;make binary
        sub     dl,1
        mov     ah,0eh  ;Funktion select drive
        int     dos
        pop     dx
chg_dir:
;       mov     ah,3bh          ;Funktion Change Directory
        stc
        mov     ax,713bh        ;Funktion change Directory
        int     dos

        mov     si,offset curdir
        xor     dl,dl           ;aktuelles Laufwerk
        stc
        mov     ax,7147h        ;get current directory
        int     dos


        mov     si,offset curdir        ;Anzeige aktuellen Pfad
        call    printa                  ;bei Programmende

        jmp     ret0


;Hilfstextanzeige wenn Aufruf ohne Parameter, nur Spaces als Parameter
hilfe:  call    prmsg           ;zusaetzlicher Hinweistext
        dbl     'Usage: GO pfad'
        db      'Als pfad wird ein Pfadname, Teile eines Pfadnamens,'
        dbl     '/ oder \ oder .. erwartet.'
        db      'Die aktuell auf der Platte vorhandene Directory-Struktur'
        dbl     ' laesst sich mit'
        db      'tree /A ',3eh;'
        dbl     'datei.txt'
        dbl     'speichern.'
        db      cr
        dbl     "Directories:"
        db      0

        lea     si,names        ;Anzeige der gespeicherten Directorynamen
hilfe1: call    printa          ;Anzeige eines Namens
        cmp     b[si],0         ;Tabelle abgearbeitet ?
        jnz     hilfe2          ;nein

        jmp     hilfe5          ;Programmende

hilfe2: mov     ah,3            ;Cursorposition bestimmen, um Abstand
        xor     bh,bh           ;zum naechsten Directorynamen zu erzeugen
        int     10h
        cmp     dl,48           ;Zeilenende?
        jle     hilfe3          ;nein
        print_crlf              ;ja: CR und naechsten Directorynamen anzeigen
        jmps    hilfe1

hilfe3: push    dx
        print_chr ' '           ;1 Space ausgeben
        pop     dx
        inc     dl              ;wegen des Spaces
        and     dl,0fh          ;Tabulator auf 16

        push    si              ;passende Anzahl Spaces ausgeben
        lea     si,spaces15
        xor     dh,dh
        add     si,dx
        call    printa          ;Ausgabe Spaces
        pop     si
        jmps    hilfe1

hilfe5: jmp     ret1            ;Errorlevel 1 zurueckgeben da Parameterfehler

        end     _start

Letztes Upload: 24.03.2023 um 11:35:15 • Impressum und Datenschutzerklärung