FAQ для раздела Assembler, MASM, TASM
25.06.2013, 13:20. Просмотров 104629. Ответов 64
Ответ
Поиск файлов и вывод содержимого каталога на экран. DOS Поиск файлов в DOS реализуется, как правило, через функции 4Eh и 4Fh прерывания 21h. Эти функции позволяют обнаруживать в заданном каталоге или на заданном устройстве файлы с именами, соответствующими заданному образцу.
В DOS существует возможность обращаться к группе файлов, задав так называемую маску имени. При задании маски используются обозначения: ? - любой символ, * - любая группа символов. Например: - *.* - все файлы
- *.СОМ - все файлы с расширением .СОМ
- ?С.ЕХЕ - под ? понимается любая ОДНА буква, таким образом BC.EXE и NC.EXE удовлетворяют условию, а TCC.EXE - нет.
Функции 4h и 4Fh помещают результат своей работы в область передачи данных (DTA), организованную следующим образом: Байты | Содержимое | 0 - 14h | Зарезервировано | 15h | Атрибут | 16h - 17h | Время и дата файла | 1Ah - 1Dh | Размер файла | 1Eh - 2Ah | Имя файла |
По умолчанию область DTA размещается в программе по адресу DS:80h, то есть там же, где и параметры командной строки. Для того, чтобы программа могла одновременно пользоваться и командной строкой и функциями поиска, часто применяется функция 1Ah прерывания 21h, предназначенная для перемещения области DTA в другое место памяти.
Приведем формат вызова функций поиска:
Код
AH:=4Eh или 4Fh
CX:=Атрибут файла
DS:DX:= Адрес строки маски имени
Атрибут файла - это байт, определяющий внутренние характеристики файла: Бит | Название | Перевод | Значение | 0 | Read only | Только для чтения | в этот файл нельзя писать и его нельзя удалить | 1 | Hidden | Скрытый | файл скрывается от показа, пока явно не указано обратно | 2 | System | Системный | содержание файла критично для работы операционной системы | 3 | Label | Метка тома | | 4 | Directory | Каталог | файл, содержащий записи о входящих в него файлах. Каталоги могут содержать записи о других каталогах, образуя древовидную структуру | 5 | Archive | Архивный | файл изменен после резервного копирования или не был скопирован программами резервного копирования | 6 | | Не используется | | 7 | | Не используется | | 8 | Shared | Разделяемый (Novell NetWare) | возможность одновременной работы с файлом в локальной вычислительной сети нескольким пользователям одновременно |
Если в байте атрибутов установить бит 4 в 1, то функции поиска будут искать каталоги (которые с точки зрения DOS также являются файлами). При установленном бите 1 функции поиска обнаружат скрытые файлы, например в корневом каталоге диска С: файлы MSDOS.SYS и IO.SYS. Для поиска обычных файлов достаточно просто заказать нулевое значение байта атрибутов.
Приведем пример программы, ищущей и отображающей на экране имена всех файлов с расширением .СОМ в текущем каталоге: Assembler | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
| ; masm dos com #
.286
.model tiny
.code
org 80h
; Область передачи данных по умолчанию
dta db 15h dup (0)
attrib db 0
timdat dw 0
dw 0
fsize dd 0
fname db 0Eh dup (0)
org 100h
; Начало программы
start: mov ah,4Eh; Ищем 1-й файл
xor cx,cx
mov dx,offset maska
int 21h
jc net
povtor:mov si,offset fname
pechat:lodsb; Печатаем имя
test al,al
je poisk
int 29h
jmp pechat
poisk: mov al,0Dh; Переводим строку
int 29h
mov al,0Ah
int 29h
mov ah,4Fh; Ищем следующий файл
int 21h
jnc povtor
net: ret ; Файлов больше нет, конец
maska db '*.com',0; Маска для поиска
end start |
|
Поиск файлов и вывод содержимого каталога на экран.
Используем системную команду DIR Вывод списка файлов и подкаталогов из указанного каталога.
Код
DIR [диск:][путь][имя_файла] [/A[[:]атрибуты]] [/B] [/C] [/D] [/L] [/N]
[/O[[:]порядок]] [/P] [/Q] [/S] [/T[[:]время]] [/W] [/X] [/4]
где [диск:][путь][имя_файла] Диск, каталог и/или файлы, которые следует включить в список.
/A | Вывод файлов с указанными атрибутами. | | атрибуты | D | Каталоги | R | Доступные только для чтения | H | Скрытые файлы | A | Файлы для архивирования | S | Системные файлы | | Префикс "-" имеет значение НЕ | /B | Вывод только имен файлов. | /C | Применение разделителя групп разрядов для вывода размеров файлов (по умолчанию). Для отключения этого режима служит ключ /-C. | /D | Вывод списка в несколько столбцов с сортировкой по столбцам. | /L | Использование нижнего регистра для имен файлов. | /N | Отображение имен файлов в крайнем правом столбце. | /O | Сортировка списка отображаемых файлов. | | порядок | N | По имени (алфавитная) | S | По размеру (сперва меньшие) | E | По расширению (алфавитная) | D | По дате (сперва более старые) | G | Начать список с каталогов | | Префикс "-" обращает порядок | /P | Пауза после заполнения каждого экрана. | /Q | Вывод сведений о владельце файла. | /S | Вывод списка файлов из указанного каталога и его подкаталогов. | /T | Выбор поля времени для отображения и сортировки | | время | C | Создание | A | Последнее использование | W | Последнее изменение | /W | Вывод списка в несколько столбцов. | /X | Отображение коротких имен для файлов, чьи имена не соответствуют стандарту 8.3. Формат аналогичен выводу с ключом /N, но короткие имена файлов выводятся слева от длинных. Если короткого имени у файла нет, вместо него выводятся пробелы. | /4 | Вывод номера года в четырехзначном формате |
Стандартный набор ключей можно записать в переменную среды DIRCMD. Для отмены
их действия введите в команде те же ключи с префиксом "-", например: /-W. Assembler | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| ; masm dos com #
.286
.model tiny
.code
org 100h
start: mov ah,4Ah ;allow mem alloc.
mov bx,10h ;новый размер блока в параграфах
int 21h
mov si,offset command_line
int 2Eh ; execute a command using BASE LEVEL
mov ah,4Ch ;выходим из программы
int 21h
command_line db N,'DIR',0Dh
N = $ - command_line - 1
end start |
|
или так Assembler | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| ; masm dos com #
.286
.model tiny
.code
org 100h
start: mov si,offset string
mov cx,N
@@: push cx
lodsb
mov ah,5 ;номер функции
mov cl,al;передача параметра через регистр CL, содержимое CH=0
int 16h
pop cx
loop @b
retn
string db 'DIR',0Dh; не более 15 символов
N = $ - string
end start |
|
или так Assembler | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| ; masm dos com #
.286
.model tiny
.code
org 100h
start: mov bx,100h ;выделим блок памяти в 256 параграфов
mov ah,4Ah
int 21h
mov bx,offset parametrs ;указываем на блок параметров
mov [bx+4],cs
mov dx,offset filename
mov ax,4B00h;загрузить и выполнить программу из командной строки
int 21h
retn ;выход в DOS
command_line db N,'/c DIR',0Dh
N = $-command_line-1;длина командной строки
;командная строка типа pascal, начинается с байта длины строки, заканчивается
;ASCII-кодом клавиши Enter (0Dh). При передаче команды CMD.EXE нужно указать /С перед
;строкой (требование вызова вторичного командного процессора). Программу cmd.exe
;из папки windows\system32\ проще разместить в том же каталоге, что и программа
filename db 'cmd.exe',0
parametrs dw 0,command_line,5 dup(0);блок параметров
end start |
|
или вот так Assembler | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
| ; masm dos com #
.286
.model tiny
.code
org 100h
start: mov ah,4Ah ;модифицируем назначенную память
mov bx,100h ;новый размер блока в параграфах
int 21h
or bx,-1 ;требуемое число параметров для выполнения
mov ah,48h ;вделить блок памяти
int 21h ;возвращает в bx размер наибольшего доступного блока
;памяти в параграфах
mov ah,48h ;вделить блок памяти, в bx действительно доступная память
int 21h ;возвращает в ах сегментный адрес выделенного блока
mov es,ax ;es:=new PSP
mov ss,ax ;ss:=new PSP
xchg dx,ax ;dx:=new PSP
mov ah,26h ;создать новый префикс программного сегмента
int 21h
mov dx,offset filename
mov di,80h ;указатель на командную строку
mov cx,(N+1)/2 ;копируем по два байта за раз, N округлен в большую
;сторону к числу кратному два, поэтому добавочный movsb не нужен
mov si,offset command_line
rep movsw ;создаем командную строку для запуска command.com
mov ax,3D00h ;открыть command.com на чтение
int 21h
xchg bx,ax ;дескриптор файла в bx
xor cx,cx ;cx=dx=0
xor dx,dx
mov ax,4202h ;установить файловый указатель на конец файла
int 21h
push ax ;сохраним в стеке длину файла command.com
mov ax,4200h ;установить файловый указатель на начало файла
int 21h
mov dx,es ;пересчитываем чему должен быть равен dx из расчета,
add dx,10h ;что cs*10h+dx=es*10h+100h
mov cx,cs
sub dx,cx
shl dx,4 ;в dx адрес буфера, куда будет скопирован command.com
pop cx ;в сх число байтов для чтения
mov ah,3Fh ;читаем command.com в буфер
int 21h
mov ah,3Eh ;закрыть файл command.com
int 21h
mov ax,es ;ds:=new PSP
mov ds,ax ;при старте СОМ-файла cs=ds=es=ss=PSP ip=100h
push es ;новое значение cs:=new PSP
push 100h ;новое значение ip:=100h
retf ;запускаем command.com для создания файла myfile.txt
filename db 'c:\windows\system32\command.com',0;полный путь к command.com
command_line db N-1,'/c DIR',0Dh
N = $ - command_line
db 0; если N нечетное, то копируется и добавочный нулевой символ
end start |
|
Поиск файлов и вывод содержимого каталога на экран. Windows Пример из книги Пирогова "Ассемблер для Windows". Программа осуществляет поиск в указанном или текущем каталоге. Поиск проходит по дереву каталогов, начиная с заданного Assembler | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
| ; masm windows console #
.686
.model flat
include \masm32\include\windows.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
;объявление используемых функций Windows (внешние ссылки)
extern _imp__wsprintfA:dword
extern _imp__CharToOemA@8:dword;
extern _imp__GetStdHandle@4:dword;
extern _imp__WriteConsoleA@20:dword;
extern _imp__ReadConsoleA@20:dword;
extern _imp__ExitProcess@4:dword;
extern _imp__GetCommandLineA@0:dword;
extern _imp__lstrcat@8:dword;
extern _imp__lstrcpyA@8:dword;
extern _imp__FindFirstFileA@8:dword;
extern _imp__FindNextFileA@8:dword;
extern _imp__FindClose@4:dword;
extern _imp__lstrlenA@4:dword
_FIND STRUC;структура, используемая для поиска файлов при помощи
;функций FindFirstFileA и FindNextFileA
ATR dd ?;атрибут файла
CRTIME dd ?;время создания файла
dd ?
ACTIME dd ?;время доступа к файлу
dd ?
WRTIME dd ?;время модификации файла
dd ?
SIZEH dd ?;размер файла
SIZEL dd ?
dd ?;резерв
dd ?
NAM db 260 dup(0);длинное имя файла
ANAM db 14 dup(0);короткое имя файла
_FIND ENDS
.code
start: push STD_INPUT_HANDLE
call _imp__GetStdHandle@4;получаем HANDL1 для ввода
mov HANDL1,eax
push STD_OUTPUT_HANDLE
call _imp__GetStdHandle@4;получаем HANDL для вывода
mov HANDL,eax
call NUMPAR ;получить количество параметров
mov PAR,eax
dec eax;если параметр один, то искать в текущем каталоге
je NO_PAR
mov edx,2;получить параметр номером edi
lea ebx,BUF
call GETPAR
jb NO_PAR
mov edi,3;подключить параметр - маску поиска
lea ebx,MASKA
call GETPAR
NO_PAR: push offset BUFER
call FIND
push NUMF;вывести количество файлов
push offset FORM
push offset BUFER
call _imp__wsprintfA
add esp,12
lea eax,BUFER
mov edi,1
call WRITE
push NUMD;вывести количество каталогов
push offset FORM1
push offset BUFER
call _imp__wsprintfA
add esp,12
lea eax,BUFER
mov edi,1
call WRITE
_END: push 0
call _imp__ExitProcess@4
;---------------------------------------------------------------
WRITE PROC;вывести строку с переводом строки
push eax
push eax
call _imp__lstrlenA@4;получить длину параметра
pop ebx
mov dword ptr [ebx+eax],0D0Ah
add eax,2
NO_ENT: push 0;резерв
push offset LENS;выведено символов
push eax;длина строки
push ebx;адрес строки
push HANDL;HANDL вывода
call _imp__WriteConsoleA@20;вывести строку
RET
WRITE ENDP
;-------------------------------------------------
NUMPAR PROC;определение параметров в командной строке
call _imp__GetCommandLineA@0
mov esi,eax
xor ecx,ecx
mov edx,1
L1: cmp byte ptr [esi],0
je L4
cmp byte ptr [esi],32
je L3
add ecx,edx;номер параметра
xor edx,edx
jmp L2
L3: or edx,1
L2: inc esi
jmp L1
L4: mov eax,ecx
ret
NUMPAR ENDP
;------------------------------------------------------
GETPAR PROC;в edi указатель на буфер, куда помещен параметр
;в ebx номер параметра
call _imp__GetCommandLineA@0
mov esi,eax
xor ecx,ecx
mov edx,1
L10: cmp byte ptr [esi],0
je L40
cmp byte ptr [esi],32
je L30
add ecx,edx;номер параметра
xor edx,edx
jmp L20
L30: or edx,1
L20: cmp ecx,edi
jne L50
mov al,[esi]
mov [ebx],al
inc ebx
L50: inc esi
jmp L10
L40: mov byte ptr [ebx],0
ret
GETPAR ENDP
FIND PROC;поиск в каталоге файлов и вывод имени каталога в BUF
FINDH equ [ebp-4]
DIRS equ [ebp-304]
DIRSS equ [ebp-604]
DIRV equ [ebp-904]
DIR equ [ebp+8]
enter 904,0
xor eax,eax
lea edi,DIRV
mov ecx,900/4
rep stosd
push DIR
call _imp__lstrlenA@4
mov ebx,eax
mov edi,DIR
cmp byte ptr [edi],0
je _OK
cmp byte ptr [edi+ebx-1],'\'
je _OK
push offset AP
push DIR
call _imp__lstrcat@8
_OK: push DIR
lea eax,DIRSS
push eax
call _imp__lstrcpyA@8
push offset MASKA;путь с маской
push DIR
call _imp__lstrcat@8
push offset FIN;здесь начало поиска
push DIR
call _imp__FindFirstFileA@8
inc eax;cmp eax,-1
je _ERR
dec eax
mov FINDH,eax;сохранить дескриптор поиска
LF: cmp byte ptr FIN.NAM,".";исключить файлы "." и ".."
je _FF
lea eax,DIRSS
push eax
lea eax,DIRS
push eax
call _imp__lstrcpyA@8
push offset FIN.NAM
lea eax,DIRS
push eax
call _imp__lstrcat@8
test byte ptr FIN.ATR,10h;не каталог ли?
je NO_DIR
push offset DIRN
lea eax,DIRS
push eax
call _imp__lstrcat@8
inc NUMD
dec NUMF
mov PRIZN,1
lea eax,DIRS
push eax
call OUTF
jmp _NO
NO_DIR: lea eax,DIRS
push eax
call OUTF
mov PRIZN,0
_NO: cmp PRIZN,0
jz _F
lea eax,DIRSS
push eax
lea eax,DIRV
push eax
call _imp__lstrcpyA@8
push offset FIN.NAM
lea eax,DIRV
push eax
call _imp__lstrcat@8
lea eax,DIRV
push eax
call FIND
_F: inc NUMF
_FF: push offset FIN
push FINDH
call _imp__FindNextFileA@8;продолжение поиска
test eax,eax;cmp eax,0
jne LF
push FINDH
call _imp__FindClose@4;закрыть поиск
_ERR: leave
ret 4
FIND ENDP
OUTF proc
STRN equ [ebp+8]
push ebp
mov ebp,esp
push STRN
push STRN
call _imp__CharToOemA@8;преобразовать строку
mov eax,STRN
mov edi,1
call WRITE;здесь вывод результата
inc NUM
cmp NUM,22;конец страницы?
jne NO
mov NUM,0
mov edi,1
lea eax,TEXT
call WRITE;ждать вывод строки
push 0
push offset LENS
push 10
push offset BUFIN
push HANDL1
call _imp__ReadConsoleA@20
NO: pop ebp
ret 4
OUTF endp
;data------------------------------------------
BUF db 0
db 100 dup (?)
LENS dd 100;количество выведенных символов
HANDL dd ?
HANDL1 dd ?
MASKA db "*.*",0
AP db "\",0
FIN _FIND <0>
TEXT db '„«п Їа®¤®«¦Ґ*Ёп **¦¬ЁвҐ Є«*ўЁиг ENTER',13,10,0;"Нажмите клавишу Enter" в кодировке CP-866
BUFIN db 10 dup(0)
NUM db 0
NUMF dd 0;счетчик файлов
NUMD dd 0;счетчик каталогов
FORM db '—Ёб«® **©¤Ґ*ле д*©«®ў: %lu',0;"Число найденных файлов"
FORM1 db '—Ёб«® **©¤Ґ*ле Є*в*«®Ј®ў: %lu',0;"Число найденных каталогов"
BUFER db 100 dup(0)
DIRN db " <DIR>",0
PAR dd 0;количество параметров
PRIZN db 0
end start |
|
Вернуться к обсуждению: FAQ для раздела Assembler, MASM, TASM
6
|