Home |
8086 Assembler,
|
Zurück zur Assemblerauswahlseite |
|
Die 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 Progamm 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 i 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 Attributbytes. Innerhalb 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:
Etwas 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 ähnlich 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
inc si ;Programmaufruf erfolgte ohne
mov w es:[si],002ah ;Parameter: wir denken uns einen *
jmps ls20
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 ;Attrubut 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
| ||||||||||||||||||||||||