Dies ist ein 32-bit-Nachbau des 16-bit-Programms LS.com.
Beide Versionen leisten etwa das Gleiche. Allerdings unterscheiden sie sich etwas im Format des Aufrufs und im Format der Anzeige. Die hier gezeigte 32-bit-Version baut auf dem Programmbeispiel \masm32\examples\exampl02\dir\mdir.asm des MASM32-SDK auf. Das Programmbeispiel demonstriert, wie man mit den API-Funktionsaufrufen FindFirstFile() und FindNextFile()ein Verzeichnis auf Dateinamen absuchen kann, um die Dateinamen auf dem Bildschirm anzuzeigen. Außerdem wird eine vom vorhergehenden Beispiel abweichende Methode zum Einlesen der Kommandozeile genutzt. Der MASM32-SDK beinhaltet in \masm32\datetime ein Paket zur Behandlung von Datums- und Zeitfunktionen. Eine Bedienungsanleitung dazu ist in der interaktiven Hilfe des MASM32-SDKs vorhanden. Die Anwendung des Pakets erleichtert die Programmierung der Datums- und Zeitanzeige. |
AblaufbeispielDreimal wird LS.exe aufgerufen. Der zweite Aufruf zeigt eine Schwachstelle beim Aufruf mit dem Parameter ..\help - statt des Verzeichnisinhalts wird nur der Verzeichnisname angezeigt. Erst mit dem Aufruf ..\help\*.* gelingt die Anzeige des Verzeichnisinhalts. Der dritte Aufruf zeigt Dateinamen mit dem Attribut C. Es handelt sich um Dateien in einem unter dem Dateisystem NTFS komprimierten Verzeichnis. Angezeigt wird hier die unkomprimierte Dateilänge.Beim 16-bit-Programm LS.com erfolgte die Längenanzeige hexadezimal. Beim 32-bit-Programm LS.exe erfolgt die Längenangabe dezimal. Die dezimale Längenangaben war in diesem Fall bequemer zu programmieren. Das hier gezeigte Programm kann verbessert werden. So könnte bei der Anzeige der Text „bytes” entfallen ... |
0:20:29:56 C:\masm32\Uebung>ls 16.12.2013 19:29:39 ---D-- 0 bytes . 16.12.2013 19:29:39 ---D-- 0 bytes .. 24.07.2007 07:31:52 ----A- 975 bytes DateTimeToStringShort.asm 16.12.2013 18:21:30 ----A- 1.099 bytes DateTimeToStringShort24.asm 15.12.2013 06:48:34 ---D-- 0 bytes enum 16.12.2013 15:58:15 ---D-- 0 bytes Konsole 16.12.2013 19:29:22 ----A- 9.066 bytes ls.asm 16.12.2013 19:29:39 ----A- 4.096 bytes ls.exe 16.12.2013 19:29:39 ----A- 2.436 bytes ls.obj 13.12.2013 08:02:40 ----A- 3.075 bytes mdir_org.asm 15.12.2013 08:09:16 ----A- 3.072 bytes mdir_org.exe 15.12.2013 08:09:16 ----A- 1.428 bytes mdir_org.obj 15.12.2013 06:48:34 ---D-- 0 bytes Pgms 16.12.2013 18:08:34 ---D-- 0 bytes PGms_gesichert Press any key to continue ... 0:20:30:15 C:\masm32\Uebung>ls ..\help 16.12.2013 14:54:08 ---D-C 0 bytes help Press any key to continue ... 0:20:30:33 C:\masm32\Uebung>ls ..\help\*.* 16.12.2013 14:54:08 ---D-C 0 bytes . 16.12.2013 14:54:08 ---D-C 0 bytes .. 16.10.2007 08:46:28 ----AC 37.579 bytes asmintro.chm 04.08.2008 23:43:12 ----AC 20.483 bytes DateTime.chm 29.12.2007 15:31:22 ----AC 45.235 bytes fpuhelp.chm 04.12.2011 06:51:03 ----AC 90.027 bytes hlhelp.chm 20.03.2011 01:02:44 ----AC 28.131 bytes imdialog.chm 20.10.2007 11:49:38 ----AC 96.302 bytes masm32.chm 06.11.2011 00:33:49 ----AC 89.395 bytes masmlib.chm 16.12.2013 14:54:08 ----AC 21.105 bytes masmlib.chw 22.10.2007 11:06:20 ----AC 59.501 bytes opcodes.chm 10.08.2008 03:28:08 ----AC 85.204 bytes qeditor.chm 11.06.2008 23:54:14 ----AC 23.286 bytes VKDebug.chm 16.12.2013 15:58:45 -H--AC 455.740 bytes win32.GID 26.11.1996 11:00:00 ----AC 20.033.075 bytes win32.hlp Press any key to continue ... |
Das QuellprogrammEine kurze Interpretation steht unterhalb des Quellprogrammtextes.comment # This program uses the FindFirstFile() FindNextFile() API functions to perform a directory list search which is displayed at the console. This file should be built with the "Console assemble & link" option on the project menu. Zur WIN32_FIND_DATA STRUCT: --------------------------- dwFileAttributes DWORD ? ftCreationTime FILETIME <> ftLastAccessTime FILETIME <> ftLastWriteTime FILETIME <> nFileSizeHigh DWORD ? nFileSizeLow DWORD ? dwReserved0 DWORD ? dwReserved1 DWORD ? cFileName BYTE MAX_PATH dup (?) cAlternateFileName BYTE 14 dup (?) FILETIME STRUCT dwLowDateTime DWORD ? dwHighDateTime DWORD ? Bitmaske für die Datei-Attribute: FILE_ATTRIBUTE_READONLY equ 1 FILE_ATTRIBUTE_HIDDEN equ 2h FILE_ATTRIBUTE_SYSTEM equ 4h FILE_ATTRIBUTE_DIRECTORY equ 10h FILE_ATTRIBUTE_ARCHIVE equ 20h FILE_ATTRIBUTE_NORMAL equ 80h FILE_ATTRIBUTE_TEMPORARY equ 100h FILE_ATTRIBUTE_COMPRESSED equ 800h ------------------------------------------------------------------- Zur externen Prozedur DateTimeToStringShort24: This procedure converts a DATETIME (same structur as FILETIME) to a date and time string in the system's short date and 24-hour format. Usage: INVOKE DateTimeToStringShort24, pdt, pszShort24 pdt is a pointer to the DATETIME [IN] pszShort24 is a pointer to the resulting ASCIIZ string [OUT] Returns a PTR BYTE in eax: a pointer to the resulting string on success, NULL on error Mehr Information: siehe MASM32-SDK, Help, Kapitel Date Time Reference. Die Assemblerquelle der Prozedur ist \masm32\DateTime.inc\DateTimeToStringShort24, die zugehörige Objektdatei ist in \masm32\lib\DateTime.lib eingebunden. ------------------------------------------------------------------- # .386 .model flat, stdcall option casemap :none ; case sensitive ; ------------------------------------------- include \masm32\include\windows.inc include \masm32\macros\macros.asm ;nachgetragen include \masm32\include\user32.inc include \masm32\include\kernel32.inc include \masm32\include\masm32.inc include c:\masm32\include\msvcrt.inc ;nachgetragen INCLUDE \masm32\include\DateTime.inc ;nachgetragen includelib \masm32\lib\user32.lib includelib \masm32\lib\kernel32.lib includelib \masm32\lib\masm32.lib includelib \masm32\lib\msvcrt.lib ;nachgetragen INCLUDELIB \masm32\lib\DateTime.lib ;nachgetragen ; ------------------------------------------- Main PROTO ;erforderlich weil Main eine Prozedur ist .data notfound db "Datei nicht gefunden" crlf db 13,10,0 ;ergaenzt ggf. notfound wCard db "*",0 spc db " ",0 bytes db " bytes ",0 ;fMtStrinG db "%lu",0 fMtStrinG db "%10.1lu",0 mitPunkt db 14 dup (" "),0 ;Space, 13 bytes,0 attrs db "RHSDAC " msg_attrs_spc db " " ;msg_attrs mit führendem Space msg_attrs db "RHSDAC " db 0 ;hier Ausgabeende pszShort24 db 64 dup (0) ; ######################################################################### .code start: invoke Main inkey invoke ExitProcess,0 ; ######################################################################### Main proc LOCAL hSearch :DWORD ; search handle LOCAL sizeBuffer[16]:BYTE LOCAL fBuffer[256]:BYTE ; file name buffer LOCAL clBuffer[128]:BYTE ; command line buffer LOCAL wfd :WIN32_FIND_DATA invoke GetCL,1,ADDR clBuffer ; get arg 1 .if eax != 1 ; if no arg mov ecx, LENGTHOF wCard ; copy * into mov esi, offset wCard ; clBuffer lea edi, clBuffer rep movsb .endif invoke FindFirstFile,ADDR clBuffer,ADDR wfd .if eax == INVALID_HANDLE_VALUE invoke StdOut,ADDR clBuffer ; Suchbegriff invoke StdOut,ADDR spc invoke StdOut,ADDR notfound ; display "not found" message jmp TheEnd .else mov hSearch, eax .endif mov al, [wfd.cFileName] cmp al, "." ;keine Anzeige weiterer Directoryinfos ; je nxt INVOKE DateTimeToStringShort24, ADDR wfd.ftLastWriteTime, ADDR pszShort24 invoke StdOut, ADDR pszShort24 mov eax,[wfd.dwFileAttributes] ;Attribute zur Anzeige call zeige_attribute invoke wsprintf,ADDR sizeBuffer,ADDR fMtStrinG,wfd.nFileSizeLow lea esi,sizeBuffer+10 lea edi,mitPunkt+13 mov ecx,10 ;10 Stellen call schiebe ;Tausenderpunkte in den Laengenstring invoke StdOut,ADDR mitPunkt invoke StdOut,ADDR bytes invoke StdOut,ADDR wfd.cFileName nxt: invoke StdOut,ADDR crlf call restore_msg_attrs @@: invoke FindNextFile,hSearch,ADDR wfd cmp eax, 0 je lpOut mov al, [wfd.cFileName] cmp al, "." ;keine Anzeige weiterer Directoryinfos je nxt1 INVOKE DateTimeToStringShort24, ADDR wfd.ftLastWriteTime, ADDR pszShort24 invoke StdOut, ADDR pszShort24 mov eax,[wfd.dwFileAttributes] ;Attribute zur Anzeige call zeige_attribute invoke wsprintf,ADDR sizeBuffer,ADDR fMtStrinG,wfd.nFileSizeLow lea esi,sizeBuffer+10 lea edi,mitPunkt+13 mov ecx,10 ;10 Stellen call schiebe ;Tausenderpunkte in den Laengenstring invoke StdOut,ADDR mitPunkt invoke StdOut,ADDR bytes invoke StdOut,ADDR wfd.cFileName nxt1: invoke StdOut,ADDR crlf call restore_msg_attrs jmp @B lpOut: invoke FindClose,hSearch TheEnd: ret Main endp ; ------------------------- ;Fuegt Tausenderpunkte in die Zahl ein - die Zahl wird ;entsprechend auseinandergeschoben ;Auruf: esi asdresiert den von-Bereich, rechter Rand ;Auruf: edi asdresiert den nach-Bereich, rechter Rand ; ecx gibt die Stellenanzahl des Von-Bereichs an ; ------------------------- schiebe: mov al,[esi] ;Zeichenuebertrag mov [edi],al dec esi ;beide Zeiger nach links dec edi mov ah,[esi] cmp ah," " ;vorheriges Zeichen ein Blank? je @F ;dann keine Tausenderpunkte mov ah,"." @@: cmp ecx,10-3 ;war es die Tausenderstelle? jne @F mov [edi],ah dec edi @@: cmp ecx,10-6 ;bei der Million? jne @F mov [edi],ah dec edi @@: cmp ecx,10-9 ;bei der Milliarde? jne @F mov [edi],ah dec edi @@: loop schiebe ret ;------------------------ ; Attribut zum Anzeigetext RHSDAC ; Dabei wird das Feld msg_attrs von links nach rechts verändert ; Die Dateiattribute stehen bei Aufruf in eax ;------------------------ zeige_attribute: mov ecx,12 ;12-mal schieben ; mov ax,[esi] ; mov ax,8bfh ;RHSDA lea edi,msg_attrs ls55: cmp ecx,9 ;Bits Wertigkeit 8, 64, 128, 256, 512, und 1024 je ls59 ;ignorieren cmp ecx,6 je ls59 cmp ecx,5 je ls59 cmp ecx,4 je ls59 cmp ecx,3 je ls59 cmp ecx,2 jne ls60 ;nicht ignorieren! ls59: rcr ax,1 ;ignorieren! jmp ls70 ls60: rcr ax,1 jc ls65 ;Attribut gesetzt temp1: mov byte ptr [edi],'-' ls65: inc edi ls70: loop ls55 invoke StdOut,offset msg_attrs_spc ret ; ------------------------- ; Inhalt von msg_attrs wieder herstellen ; Wird nach Anzeige des Dateinamens aufgerufen ; ------------------------- restore_msg_attrs: mov esi,offset attrs mov edi,offset msg_attrs mov ecx,6 ;6 Bytes Laenge @@: mov al,[esi] mov [edi],al inc esi inc edi loop @B ret ; ######################################################################### end start |
Interpretation des QuellprogrammsDas hier vorgestellte Programm ist nicht die endgültige Programmversion. Deshalb sind noch einige nicht benötigte Definitionen im Datenbereich vorhanden. Einige nicht mehr benötigte Befehle sind lediglich auskommentiert. include und includelib: Der Kommentar „nachgetragen” kennzeichnet die gegenüber \masm32\examples\exampl02\dir\mdir.asm ergänzten Zeilen. .data: Die Formatierungszeichenkette "%lu",0 des ursprünglichen Programmes wurde durch "%10.1lu",0 ersetzt. Die neue Definition erzeugt eine stets 10-stellige Zahl. Von ihr wird zumindest die Einerstelle als Ziffer erhalten. Bis zu 9 führende Nullen werden durch Zwischenräume (Spaces) ersetzt. Die 10-stellige Zahl durchläuft vor ihrer Anzeige eine Textaufbereitung in dem Unterprogramm schiebe. Das Unterprogramm ergänzt Punkte bei den Tausenderstellen. Wenn links neben der der jeweiligen Tausenderstelle bereits ein Space steht, wird statt eines Punktes ein Space eingefügt. .code start: Das Programm wird mit invoke ExitProcess,0 beendet. Bei den vorhergehenden Beispielen wurde an dieser Stelle das in \masm32\macros\macros.asm definierte Macro „exit” genutzt. In beiden alternativen Schreibweisen
invoke GetCL,1,ADDR Buffer liest den ersten Aufrufparameter von der Kommandozeile. Sofern kein Aufrufparameter angegeben wurde, denkt sich das Programm ein Sternchen für „alles”. invoke FindFirstFile,ADDR Buffer,ADDR wfd sucht die erste passende Datei gem. dem angegebenen Pfad. Dieser Aufruf erfolgt einmalig. Sofern keine erste Datei gefunden wird, erfolgt die Anzeige eines Fehlerhinweises und das Programmende wird eingeleitet. Wird eine erste Datei gefunden, wird der Dateihandle für spätere Verwendung nach hSearch gesichert und der Verzeichniseintrag wird zur Anzeige gebracht. invoke FindNextFile,ADDR Buffer,ADDR wfd sucht nach Ausführung von FindFirstFile die nächste passende Datei. Wird eine solche gefunden, wird der Verzeichniseintrag angezeigt und anschließend erneut FindNextFile aufgerufen. Sofern bei eine FindNextFile-Aufruf keine nächste passende Datei gefunden wurde, gibt FindNextFile im eax-Register den Wert 0 zurück. Dies führt zur Beendigung des Programms. Aufbereitung der Anzeigezeilen: Zur Anzeige von Datum und Uhrzeit der letzten Änderung wird die Funktion DateTimeToStringShort24 aus dem weiter oben erwähnten Paket zur Behandlung von Datums- und Zeitfunktionen genutzt. Die aus dieser Funktion gewonnene Zeichenkette wird durch Anwendung des Befehls invoke StdOut, ADDR pzsShort24 unverändert zur Anzeige gebracht. Es sei bemerkt, dass in dem vorliegenden Programm der Bereich pzsShort24 mit 64 Bytes unnötig lang definiert ist: 21 Bytes hätten genügt. Zur Aufbereitung der Attributanzeige habe ich das Rotationsverfahren aus dem oben erwähnten 16-bit-Programm LS.com mit Anpassung übernommen. Es wird im Unterprogramm schiebe durchgeführt. Dessen Aufruf erfolgt von der Prozedur Main aus. In diesem Fall wirkt sich die Verwendung lokaler Variablen ungünstig aus: Im Quellprogrammtext erscheint zweimal der Aufruf von „schiebe” hinter jeweils drei identischen Programmzeilen. Könnte man diese drei Zeilen ins Unterprogramm „schiebe” übernehmen? Leider geht das nicht, weil bei lea esi,sizeBuffer+10 lea edi,mitPunkt+13die beiden Variablen lokal deklariert sind. Dagegen könnte man die beiden Programmzeilen invoke StdOut,ADDR mitPunkt invoke StdOut,ADDR bytesvor dem ret-Befehl von „schiebe” unterbringen, denn beide Variablen sind global deklariert. |