Dies Programm entstand, weil ich eine Verzeichnisanzeige in ein umfangreicheres anderes Programm einbauen wollte. Es ist bewährte Praxis, komplexe Programmaufgaben in möglichst einfacher Umgebung zu erproben. Ist die Lösung gefunden und erprobt, kann sie in das umfangreichere Programm eingebaut werden.
Unter der Bedieneroberfläche der alternativen Bedieneroberfläche 4dos werden die langen Dateinamen in ihrer verkürzten Form angezeigt. Das Programm ls schafft hier Abhilfe. Genau wie das Kommando DIR listet es Dateinamen und Unterverzeichnisse eines Verzeichnisses auf. Aufgerufen wird es durch Eingabe von Werden weder Laufwerk, Pfad noch Dateiname angegeben, wird das Inhaltsverzeichnis des aktuellen Verzeichnisses gezeigt. Bei Pfad und Dateiname sind Substitutionsangaben wie * oder ? zulässig. Um eine möglichst große Ähnlichkeit zum Kommando DIR zu erreichen, wird die Eingabe in zwei Fällen modifiziert. Zwei weitere Änderungen verbessern den Bedienkomfort.
Die unter 2 genannte Änderung ist ein kleiner Unterschied zu DIR. DIR d:\temp liefert das Inhaltsverzeichnis des Verzeichnisses d:\temp. LS d:\temp dagegen liefert lediglich eine Zeile mit Informationen über das Verzeichnis d:\temp. Erst LS d:\temp\ zeigt das Inhaltsverzeichnis des Verzeichnisses d:\temp. Zur Ermittlung des Verzeichnisinhalts werden die Funktionen 714Eh und 714Fh des MS-DOS Interrupts 21h herangezogen. Sie melden die Sucherfolge in einem Suchsatz zurück. Im Programmlisting ist seine Feldaufteilung beim Merkmal suchsatz definiert. Es werden Änderungsdatum und -zeit sowie die Attribute angezeigt. Alle diese Dinge sind etwas knifflig zu programmieren. Anzeige des AttributbytesInnerhalb der auszugebenden Zeichenkette msg_satz steht beim Merkmal msg_attrs die Zeichenkette ADSHR. Jeder Buchstabe kennzeichnet ein gesetztes Attribut. Ist das Attribut bei dem anzuzeigenden Datei- oder Verzeichnisnamen nicht gesetzt, wird der entsprechende Buchstabe durch ein Minuszeichen ersetzt. Nach der Anzeige wird die solcherart modifizierte Zeichenkette mit dem Inhalt des Feldes beim Merkmal attrs überschrieben und somit wieder hergestellt. Die Wiederherstellung ist im Programm beim Label ls80 zu finden.Anzeige von Änderungsdatum und -zeitBeim Aufruf der Funktionen 714Eh und 714Fh wird durch den Inhalt des SI-Registers diese Information im „alten” DOS-Format angefordert. Somit werden beide Informationen in jeweils einem halben Doppelwort geliefert. Jedes halbe Doppelwort ist in Bitgruppen unterteilt. Für die Anzeige müssen die Bitgruppen entsprechend aufgeteilt und von binär in dezimal und ASCII umgewandelt werden. Die Aufteilung ist:
Gewöhnungsbedürftig ist die Anzeige der Datei- oder Verzeichnislänge in hexadezimaler Schreibweise statt in Dezimal. Dadurch wird Platz in der Anzeigezeile auf dem Bildschirm gespart. Es lässt sich auch so gut erkennen, welche Datei besonders groß oder besonders klein ist. Nachfolgend sind ähnliche Anzeigen vom DIR und LS dargestellt. Beide Kommandos wurden unter der Bedieneroberfläche CMD ausgeführt. | ||||||||||||||||||||||||
D:\dos\ML\Test>dir *asm Datenträger in Laufwerk D: ist HP_D Volumeseriennummer: 402E-2809 Verzeichnis von D:\dos\ML\Test 26.02.2011 08:10 6.888 attr.asm 27.01.2011 08:10 19.631 BATC.ASM 13.02.2011 13:20 25.633 DOS.asm 15.02.2011 12:04 12.191 GO_HP.ASM 15.02.2011 12:09 12.279 GO_TBIRD.ASM 26.02.2011 08:10 6.888 LS.ASM 18.02.2011 15:39 4.134 MORE.ASM 26.02.2011 07:45 17.958 sh.asm 23.02.2011 16:07 17.719 shell.asm 17.02.2011 07:43 13.401 shellsav1.asm 18.02.2011 18:46 13.817 shellsav2.asm 06.02.2011 13:41 7.924 tee.asm 12.02.2011 13:36 4.734 test.asm 25.01.2011 04:31 1.751 VERS.ASM 14 Datei(en), 164.948 Bytes 0 Verzeichnis(se), 21.212.536.832 Bytes frei D:\dos\ML\Test>ls *asm 26.02.11 08:10 A---- 00001AE8 attr.asm 27.01.11 08:10 A---- 00004CAF BATC.ASM 13.02.11 13:20 A---- 00006421 DOS.asm 15.02.11 12:04 A---- 00002F9F GO_HP.ASM 15.02.11 12:09 A---- 00002FF7 GO_TBIRD.ASM 26.02.11 08:10 A---- 00001AE8 LS.ASM 18.02.11 15:39 A---- 00001026 MORE.ASM 26.02.11 07:45 A---- 00004626 sh.asm 23.02.11 16:07 A---- 00004537 shell.asm 17.02.11 07:43 A---- 00003459 shellsav1.asm 18.02.11 18:46 A---- 000035F9 shellsav2.asm 06.02.11 13:41 A---- 00001EF4 tee.asm 12.02.11 13:36 A---- 0000127E test.asm 25.01.11 04:31 A---- 000006D7 VERS.ASM D:\dos\ML\Test> |
.MODEL TINY ;====================================== ;ls - Directory-Anzeige aehnlich DIR ;====================================== ; FALSE EQU 0 TRUE EQU NOT FALSE ;von den mit true ausgewaehlten Unterprogrammen wird nur ;INT2ASC benoetigt (und zwar bei der Aufbereitung der Jahreszahl) dump$ equ false ;fuer mdump, rdump prompt$ equ false ;fuer PROMPT, INKJN intasc$ equ true ;fuer INT2ASC, ASC2INT string$ equ false ;fuer CMPSTR, LENSTR, INSTR, MOVSTR comment # Programm zum Erproben der Directorysuchfunktionen mit langen Namen. 25.2.2011, Fredrik Matthaei # .CODE org 100h _start: jmp around include firm.mac ;------------------------------------ ; Datenbereiche und Texte handle dw 0 msg02: dbz 'Datei nicht gefunden.' msg03: dbz 'Pfad nicht gefunden.' msg05: dbz 'Zugriff verweigert.' msg7b: dbz 'Die Syntax fuer den Datei- oder Verzeichnisnamen ist falsch.' msg7100: dbz 'Funktion 71xx wird nicht unterstuetzt.' msgxx: dbz '=Nicht aufgeschluesselter Fehler.' attrs db "ADSHR" msg_satz equ $ msg_ttmmjj db "tt.mm.jj " msg_hhmm db "hh:mm " msg_attrs db "ADSHR " msg_len db "12341234 " db 0 ;hier Ausgabeende ;Beschreibung des Suchsatzes suchsatz equ $ gef00h dd 0 ;Attribut lh 00 gef04h dq 0 ;wann erstellt lh lh 00 00 gef0ch dq 0 ;wann zuletzt zugegriffen lh lh 00 00 gef14h dq 0 ;wann zuletzt geaendert lh lh 00 00 gef1ch dd 0,0 ;Dateigroesse High :Low 00 00 : lh lh gefres db '12345678' ;reserviert curlfn db 260 dup ('0') ;langer Name cussfn db 14 dup ('1') ;kurzer Name 1111111111111 ;------------------------------------ ;Hauptprogramm around: mov si,lparm ;Laenge des Parameters xor ch,ch mov cl,es:[si] inc si or cx,cx jne ls10 ;Programmaufruf erfolgte mit Parameter ;Programmaufruf erfolgte ohne Parameter: wir denken uns einen * dec si inc cx ;cx nun auf 1 mov es:[si],cx inc si mov w es:[si],002ah ls10: add si,cx ;si zeigt nun auf cr des eingetippten Parameters mov b es:[si],ch ;aus diesem cr wird 0 ;wenn ein Doppelpunkt als letztes Zeichen eingetippt wurde, dann kommt ;ein Backslash hinzu dec si cmp b es:[si],':' jne ls12 inc si mov b es:[si],'\' ;aus / wird \ ls12: mov di, lparm+2 ;di zeigt nun auf Parameteranfang ls13: cmp b [di],0 je ls15 ;Abfrage auf Parameterende cmp b[di],'/' jne ls14 ;/ wird \ mov b[di],'\' ls14: inc di jmps ls13 ;wenn als letztes Zeichen ein Backslash steht, dann kommt ein * hinzu! ls15: cmp b es:[si],'\' jne ls20 inc si mov w es:[si],002ah ls20: mov cl,5eh ;moegliche Attribute mov ch,0 ;erforderliche Attribute mov DX,lparm+2 ;Suchmaske ab lparm +2 mov si,1 ;altes Datumsformat mov di,offset suchsatz stc ;Fehlermeldung falls MS-DOS die mov ax,714eh ;Funktion 71xx nicht unterstuetzt int21 jnc ls22 jmps fehler ls22: mov handle,ax ;handle sichern call ls50 nochmal: mov si,1 ;altes Datumsformat mov di,offset suchsatz mov bx,handle stc ;Fehlermeldung falls MS-DOS die mov ax,714fh ;Funktion 71xx nicht unterstuetzt int21 jnc ls24 jmps fehler ls24: call ls50 jmps nochmal ;-------------------------------- ;Fehlerbearbeitung und normales Programmende fehler: cmp ax,0012h ;keine weitere Datei gefunden jne fehler2 jmp fertig fehler2: cmp ax,0002 jne fehler3 mov si, offset msg02 jmps fehler99 fehler3: cmp ax,03 jnz fehler5 mov si,offset msg03 jmps fehler99 fehler5: cmp ax,05 jnz fehler7b mov si,offset msg05 jmps fehler99 fehler7b: cmp ax,7bh jnz fehler7100 mov si, offset msg7b jmps fehler99 fehler7100: cmp ax,7100h jnz fehlerxx mov si,msg7100 fehlerxx: push ax mov al,ah call hex_out pop ax call hex_out mov si, offset msgxx fehler99: call printa ;Fehlermeldung zeigen prstr <' Programmabbruch!',cr> MOV AX,4C01H ;Programmende mit Returncode 1 int21 jmp fertig ;------------------------ ; Unterprogramm Aufbereiten und Zeigen der Anzeigezeile ;------------------------------------ ; Unterprogramm Wandeln und Abspeichern 8 bit Zahl (in al) in hexa bin_hex: xchg al,ah push ax shr al,4 call binhex5 pop ax binhex5: and al,0fh daa add al,0f0h adc al,40h mov ds:[di],al inc di ret ;------------------------ ; Attribut zum Anzeigetext ls50: mov cx,6 ;6-mal schieben mov si, offset gef00h mov b al,ds:[si] mov di,offset msg_attrs+4 ls55: cmp cx,3 ;Attribut Volume Label ignorieren jne ls60 rcr al,1 jmps ls70 ls60: rcr al,1 jc ls65 ;Attribut gesetzt mov b ds:[di],'-' ls65: dec di ls70: loop ls55 ;------------------------ ; Tag letzte Aenderung zum Anzeigetext mov si,offset gef14h+2 mov w ax,ds:[si] push ax and ax,001fh ;alles ausser Tag ausmaskieren mov bl,10 div bl or ax,3030h ;Wandlung in ASCII mov w msg_ttmmjj,ax pop ax push ax sar ax,9 and ax,007fh ;alles ausser Jahreszahl ausmaskieren add ax,1980 ;Jahreszahl korrigieren xor dx,dx mov di,offset msg_ttmmjj+7 call int2asc pop ax sar ax,5 and ax,000fh ;alles ausser Monat ausmaskieren div bl or ax,3030h ;Wandlung in ASCII mov w msg_ttmmjj+3,ax ;Monat ueberschreibt Jahrtausend mov b msg_ttmmjj+5,'.' ;Punkt ueberschreibt Jahrhundert ;------------------------ ; Uhrzeit letzte Aenderung zum Anzeigetext mov si,offset gef14h mov w ax,ds:[si] push ax sar ax,5 and ax,003fh ;alles ausser Minuten ausmaskieren mov bl,10 div bl or ax,3030h ;Wandlung in ASCII mov w msg_hhmm+3,ax pop ax sar ax,11 and ax,001fh ;alles ausser Stunden ausmaskieren mov bl,10 div bl or ax,3030h ;Wandlung in ASCII mov w msg_hhmm,ax ;------------------------ ; Dateilaenge hexadezimal zum Anzeigetext. Maximal werden 4 GB ; Dateilaenge erkannt. mov di,offset msg_len mov si,offset gef1ch+6 ;Dateilaenge High Word mov ax,ds:[si] call bin_hex mov al,ah call bin_hex dec si dec si mov ax,ds:[si] ;Dateilaenge Low Word call bin_hex mov al,ah call bin_hex mov si,offset msg_satz +47 mov b ds:[si],0 ;Schutzbyte, markiert etwa Zeilenende sub si,47 call printa ; langen Dateinamen anzeigen mov si,offset curlfn call printa print_crlf ; Inhalt von msg_attrs wieder herstellen mov si,offset attrs mov di,offset msg_attrs mov cx,5 ;5 Bytes Laenge u ls80: mov b al,ds:[si] mov b ds:[di],al inc si inc di loop ls80 ret ;---------------------------------- ; Programmbeendigung fertig: mov bx,handle ;Suche beendet, Handle freigeben mov ax,71a1h int21 mov ax,4c00h ;Programm beenden int21 END _start |