EXTRN NewLine:Proc, WriteSimv:Proc, StrWrite2:Proc
; із strio.obj
EXTRN BinToAscHex:Proc, BinToAscDec:Proc
; із Binasc.obj
Start:
mov ax, @data ; встановлює в ax адресу сегмента даних
mov es, ax ; встановлює в es адресу сегмента даних
; ------Отримання даних із командного рядка
call GetParams ; отримати параметри із командного рядка
; (ds=PSP)
call NewLine ; перехід на новий рядок
; ------Виведення інформації о програмі
mov di,offset tit1 ; адреса рядка з інформацією о програмі
call StrWrite ; вивід інформації о програмі на консоль
call NewLine ; перехід на новий рядок
; ------Вибір маски
call ParamCount ; отримання в cx число параметрів
mov di, offset defaultSpec ; встановити di вказівником на
; стандартний шаблон маски
or cx, cx ; перевірка cx на наявність 0
jz @@10 ; якщо cx=0, перехід
xor cx, cx ; обнуління cx (номер параметру)
call GetOneParam ; отримати адресу параметра
; ------Виклик підпрограми обробника
@@10:
mov bx, offset Action ; поміщення в bx адреси процедури Action
call DirEngine ; виклик процедури DirEngine розгляду
; каталогу
; ------Завершення роботи
Exit:
call NewLine ; перехід на новий рядок
mov ah, 04Ch ; в ah номер функції виходу із програми
mov al, [exCode] ; в al код виходу
int 21h ; виклик DOS, завершення програми
; -------------------------------------------------------------------------------------------
; DirEngine перегляд каталогу
; -------------------------------------------------------------------------------------------
; Вхід cx:bx адреса підпрограми Action
; ds:di адреса ASCII-рядка для пошуку (маска)
; Вихід викликає процедуру Action при кожному знаходженні
; файла, що відповідає масці
Регістри ax, cx, dl, di
; -------------------------------------------------------------------------------------------
PROC DirEngine
; ------Виведення заголовку таблиці
push di ; збереження di у стеку
mov di,offset tabl ; в di зміщення рядка заголовка таблиці
; ASCII
call StrWrite ; вивід на екран заголовка таблиці
call NewLine
pop di ; відновлення di
; ------Отримання поточного DTA
push es ; збереження змінюваних регістрів
push bx
mov ah, 2Fh ; в ah номер функції DOS отримання DTA
int 21h ; отримати поточний DTA
mov [DTAseg], es ; збереження адреси сегмента DTA
mov [DTAofs], bx ; збереження адреси зміщення DTA
pop bx ; відновлення регістрів
pop es
; ------Встановлення нового DTA в глобальному 43-байтовому буфері dirData
mov dx, offset dirData ; адреса змінної dirData поміщується
; в ds:dx
mov ah, 1Ah ; а ah номер функції DOS встановлення
; DTA
int 21h ; встановлення нового DTA
; ------Перевірка каталогу на співпадіння імен файлів із маскою в ds:dx
mov ah, 4Eh ; в ah номер функції DOS першого
; пошуку
mov cx, 10h ; атрибут файлів і директорій
mov dx, di ; поміщення адреси рядка в ds:dx
jmp short @@20 ; пропуск наступної дії
@@10:
mov ah, 4Fh ; в ah номер функції DOS продовження
; пошуку
@@20:
int 21h ; пошук першого/наступного входження
jc @@99 ; вихід при помилці, або закінченні
call bx ; виклик процедури Action
jmp @@10 ; повтор дій
@@99:
; ------Відновлення початкової адреси DTA
push ds ; збереження ds у стеку
mov ds, [DTAseg] ; встановлення старої адреси DTA в ds:dx
mov dx, [DTAofs]
mov ah, 1Ah ; в ah номер функції DOS встановлення
; DTA
int 21h ; повернення до старої DTA
pop ds ; відновлення ds
ret ; завершення процедури
ENDP DirEngine
; -------------------------------------------------------------------------------------------
; Action виводить дані про файл із буфера dirData
; -------------------------------------------------------------------------------------------
; Вхід dirData DTA файла
; Вихід виводить дані про файл (назву, атрибути, дату/час створення,
; розмір)
; Регістри ax, dl, di, cx
; -------------------------------------------------------------------------------------------
PROC Action
push bx ; збереження регістрів
; ------Вивід імені файлу
mov di, offset dirData + FileName ; в di зміщення початку імені файлу
call StrWrite ; вивід імені на екран
call StrLength ; отримання в cx довжини імені
sub cx, 15 ; виявлення на скільки довжина імені
neg cx ; файлу менше поля із 15 символів
mov dl, ' ' ; в dl символ пробілу
call WriteSimv ; вивести на екран необхідну, для
; доповнення поля із 15 символів,
; кількість разів
; ------Вивід атрибутів файлу
mov al,[offset dirData + FileName -9]; в al поміщується байт атрибуту
mov cx,6 ; в cx кількість значущих бітів у байті
; атрибуту
@@01:
shr al,1 ; зсув al вправо,
; в CF поміщується молодший біт
jb @@02 ; якщо CF=1, то перехід
mov dl, ' ' ; в dl поміщується пробіл (символ виводу)
push cx ; збереження cx в стеку
mov cx,4 ; поміщення в cx кількості символів для
; виводу (4)
call WriteSimv ; вивід 4-х пробілів
pop cx ; відновлення cx
jmp @@03 ; перехід
@@02:
mov di,offset point ; в di поміщується зміщення змінної point
push cx ; збереження cx
call StrWrite ; вивід на екран зірочки
pop cx ; відновлення cx
@@03:
loop @@01 ; виконувати цикл, доки cx≠0 (6-ть разів)
; ------Вивід години створення файлу
mov bx,[offset dirData + FileName-8] ; в bx поміщується слово часу
; створення файлу
mov ax,bx ; в ax поміщуються слово години
; створення файлу
and ax,0f800h ; накладання маски
shr ax,11 ; зсув результату (отримали години)
mov cx,1
mov di,offset buffer ; di вказує на пустий буфер buffer
call BinToAscDec ; передача в змінну buffer 10-кового
; ASCII-представлення числа з ax
mov cx,2 ; в cx ширина поля виводу
call StrWrite2 ; вивід ASCII-представлення числа з ax
mov cx,1 ; встановлення в cx кількості виводів
mov dl, ':' ; передача в dl символу, що виводиться
call WriteSimv ; вивід один раз символу із dl
; ------Вивід хвилин створення файлу
mov ax,bx ; в ax поміщується слово хвилини
; створення файлу
and ax,7e0h ; накладання маски
shr ax,5 ; зсув результату (отримали хвилини)
mov cx,1
mov di,offset buffer ; di вказує на пустий буфер buffer
call BinToAscDec ; передача в змінну buffer 10-кового
; ASCII-представлення числа з ax
mov cx,2 ; в cx ширина поля виводу
call StrWrite2 ; вивід ASCII-представлення числа з ax
mov cx,1 ; встановлення в cx кількості виводів
mov dl, ':' ; передача в dl символу, що виводиться
call WriteSimv ; вивід один раз символу із dl
; ------Вивід секунд створення файлу
mov ax,bx ; в ax поміщується слово секунди
; створення файлу
and ax,1fh ; накладання маски
shl ax,1 ; помноження на 2 (отримання секунд із
; двохсекундних одиниць)
mov cx,1
mov di,offset buffer ; di вказує на пустий буфер buffer
call BinToAscDec ; передача в змінну buffer 10-кового
; ASCII-представлення числа з ax
mov cx,3 ; в cx ширина поля виводу
call StrWrite2 ; вивід ASCII представлення числа з ax
mov cx,1 ; встановлення в cx кількості виводів
mov dl, ' ' ; передача в dl символу, що виводиться
call WriteSimv ; вивід один раз символу із dl
; ------Виведення дня створення файлу
mov bx,[offset dirData + FileName-6] ; в bx слово дати створення
; файлу
mov ax,bx ; в ax слово дня створення файлу
and ax,01fh ; накладання маски
mov cx,1 ; встановлення мінімальної довжини
; перетворюваного рядка
mov di,offset buffer ; в di зміщення пустого буферу
call BinToAscDec ; заповнення буферу buffer 10-ковим
; ASCII-представленням числа з ax
mov cx,2 ; в cx ширина поля виводу
call StrWrite2 ; вивід ASCII представлення номера дня
mov cx,1 ; в cx кількість виводів
mov dl, '\' ; в dl символ для виводу
call WriteSimv ; вивід символу із dl задану кількість разів
; ------Вивід місяця створення файлу
mov ax,bx ; в ax слово місяця створення файлу
and ax,1e0h ; накладання маски
shr ax,5 ; зсув результату (отримання місяця)
mov cx,1 ; встановлення мінімальної довжини
; перетворюваного рядка
mov di,offset buffer ; в di зміщення пустого буферу
call BinToAscDec ; заповнення буферу buffer 10-ковим
; ASCII-представленням числа з ax
mov cx,2 ; в cx ширина поля виводу
call StrWrite2 ; вивід ASCII представлення номера дня
mov cx,1 ; в cx кількість виводів
mov dl, '\' ; в dl символ для виводу
call WriteSimv ; вивід символу із dl задану кількість разів
; ------Вивід року створення файлу
mov ax,bx ; в ax слово року створення файлу
and ax,0f800h ; накладання маски
shr ax,9 ; зсув результату (отримання року)
add ax,1980 ; отримання року створення
mov cx,1 ; встановлення мінімальної довжини
; перетворюваного рядка
mov di,offset buffer ; в di зміщення пустого буферу
call BinToAscDec ; заповнення буферу buffer 10-ковим
; ASCII-представленням числа з ax
mov cx,4 ; в cx ширина поля виводу
call StrWrite2 ; вивід ASCII представлення номера дня
mov cx,2 ; в cx кількість виводів
mov dl, ' ' ; в dl символ для виведення
call WriteSimv ; вивід проміжку у 2-а пробіли
; ------Вивід розміру файлу у 16-річному вигляді
mov ax,[offset dirData + FileName-2] ; в ax молодші два байти
; подвійного слова розміру файла
mov cx,1 ; в cx мінімальна довжина
; перетворюваного рядка
mov di,offset buffer ; в di зміщення буферу для результату
call BinToAscHex ; перетворення двох молодших байтів
; розміну у ASCII-рядок
call StrWrite ; вивід на екран
mov ax,[offset dirData + FileName-4] в ax містяться старші два байти
; подвійного слова розміру файла
call BinToAscHex ; перетворення у ASCII рядок
; представлення у вигляді 16-річного
; числа
call StrWrite ; вивід на екран
call NewLine ; перехід на новий рядок
pop bx ; відновлення у bx зміщення процедури
; Action
ret ; завершення процедури
ENDP Action
END Start
Схема алгоритму основної програми приведена у додатках (Додаток А).
Отримання даних із командного рядку і встановлення критерію відбору файлів (маски) реалізується за допомогою функцій модуля PARAMS.obj. Спочатку заповнюється спеціальний буфер хвостом команди і його вміст розбивається на окремі елементи (GetParams). При наявності в хвості команди параметрів, перший параметр задає маску; якщо параметри відсутні, у якості маски встановлюється стандартна '*.*' (вивід всіх файлів із директорії, в якій знаходиться програма). Основну роботу виконує функція DirEngine, в яку, за допомогою регістру bx, передається зміщення функції Action (для подальшого виклику її за зміщенням).
Функція DirEngine, за допомогою 2Fh, 1Ah, 4Eh, 4Fh функцій переривання INT21h DOS, знаходить поточне положення буфера DTA, зберігає його адресу, встановлює новий DTA у власний спеціальний буфер і за допомогою нього шукає файли, що відповідають заданій масці. При знаходженні таких файлів, керування по зміщенню передається функції Action.
Основна задача Action – обробити інформацію в DTA і вивести необхідні дані на стандартний пристрій виводу.
DTA має наступну структуру [4, 6]:
Зміщення | Довжина | |
+0 | 15H | Зарезервована, використовується функцією 4Fh INT21h DOS |
+15h | 1 | атрибут файла |
+16h | 2 | час |
+18h | 2 | дата |
+1ah | 4 | розмір файла (формат DWORD) |
+1eh | 0dh | 13-байтова ASCIIZ ім'я файлу |
Спочатку виводиться ім'я файлу, яке має наступну структуру: "filename.ext". Вивід реалізується за допомогою спеціальних функцій StrWrite, StrWriter, Length і WriteSimv із модуля STRIO.obj.