***********
; Процедура обхода всех подкаталогов заданного каталога.
; Процедура может работать и в программах формата DOS EXE !!!
; На входе:
; - Переменная StartPath (она же ScanPath) содержит имя стартового каталога.
; Имя каталога должно заканчиваться обратным слэшем ('\') !
; - В стеке смещение (word) near-функции, которая будет вызываться для каждого
; найденного каталога. При этом она может использовать ASCIIZ-строку ScanPath,
; которая содержит полное имя найденного каталога со слэшем на конце, но не
; должна изменять эту строку! При необходимости функция должна скопировать
; строку в какой-нибудь буфер, где может делать с ней все, что нужно

; Функция также не должна использовать установленный DTA, при необходимости
; нужно создать свой буфер DTA. Адрес прежнего буфера восстанавливать при
; выходе не нужно, как и регистры DS, ES, если они были изменены.
; На выходе:
; - DTA и регистры DS,BP сохранены.
; - Строка StartPath/ScanPath содержит полное имя последнего найденного каталога.
; - ES

I указывает на конец строки StartPath/ScanPath, которая была при вызове
; функции (т.е. можно сделать xor al,al / stosb и снова вызвать ScanTree).
ScanTree proc pascal
arg Func:word
local OldDTA:dword, NewDTA

TAFileInfo
; ES всегда равно первоначальному DS !!!
push ds ; Сохраняем DS
mov ah,2Fh ;адрес текущей DTA
int 21h ; Получаем адрес DTA
mov word ptr OldDTA[0],bx ; Сохраняем его...
mov word ptr OldDTA[2],es ; ...в переменной OldDTA
pop es ; Восстанавливаем DS в регистр ES (ES=DS)
lea di,ScanPath
mov cx,PathLen
xor al,al
cld ; Прямой порядок поиска scasb
repne scasb ; Ищем в имени каталога нулевой байт (конец строки)
dec di
push di ; Сохраняем указатель на ноль
push ds es ; Сохраняем DS и ES
call Func ; Вызываем функцию для стартового каталога
mov ah,1Ah
push ss
pop ds ; DS = SS (сегмент NewDTA)
lea dx,NewDTA
int 21h ; Устанавливаем свой DTA
pop es ds ; Восстанавливаем DS и ES (ES=DS)
mov ah,4Eh ; Готовимся в началу поиска
mov cx,faAnyDir ; Атрибуты (все, кроме Volume label)
lea dx,ScanPath
lea si,fMask ; SI = адрес макси поиска
; lea si,ScanMask ; SI = адрес макси поиска
pop di ; Восстанавливаем DI (указатель на конец строки)...
push di ; ...и тут же сохраняем его
cld ; Прямой порядок работы lodsb/stosb
@@CopyMask: lodsb ; Читаем в AL символ из строки [SI]
stosb ; И записываем его в конец ScanPath
or al,al ; Конец строки [SI] (AL=0) ?
jnz @@CopyMask ; Нет, копируем следующий символ
@@FindNext:
int 21h ; Начинаем/продолжаем поиск
jc @@NotFound ; Выходим, если ничего не найдено (CF=1)
push ss
pop ds ; DS = SS (сегмент NewDTA)
test NewDTA.dtaAttr,faDirectory ; Проверяем - каталог ли был найден
jz @@NotFound ; Если нет, выход
; jz @@PrepareNext ; Если нет, готовимся продолжать поиск
lea si,NewDTA.dtaName ; Адрес имени найденного файла/каталога
lodsb ; Читаем первый символ
cmp al,'.' ; Это каталоги '.' и '..'? (нам такие не нужны)
je @@PrepareNext ; Если это они, готовимся продолжать поиск
pop di ; Восстанавливаем DI (указатель на конец строки)...
push di ; ...и тут же сохраняем его
@@CopyPath:
stosb ; Записываем символ строки [SI] в конец ScanPath
lodsb ; Читаем в AL символ из строки [SI]
or al,al ; Конец строки [SI] (AL=0) ?
jnz @@CopyPath ; Нет, копируем следующий символ
mov ax,'\' ; AH = 0, AL = '\'
stosw ; Записываем слэш и ноль в конец строки
push es
pop ds ; DS = ES
push Func
call ScanTree ; Вызываем себя рекурсивно
push ss
pop ds ; DS = SS (сегмент NewDTA)
@@PrepareNext:
mov ah,4Fh ; Готовимся к функции 4Fh
lea dx,NewDTA
jmp @@FindNext ; Продолжаем поиск
@@NotFound:
pop di ; Убираем из стека DI
mov ah,1Ah
lds dx,OldDTA
int 21h ; Восстанавливаем DTA
push es
pop ds ; Восстанавливаем первоначальный DS
ret ; Выходим из процедуры
ScanTree endp
code ends
end begin
моя програма. Выложил текстом так как прикрепить вложение не получается. (((