pushdi ; регістри ax, di
xoral, al ; в alпоміщується шуканий символ 0
mov cx, 0ffffh ; в cxмаксимальна глибина пошуку
cld ; автоматичне збільшення di
repnzscasb ; шукати al, доки [di] або cxне стане 0
not cx ; логічне заперечення cx
dec cx ; зменшення cxна 1 – довжина рядка
popdi ; відновлення регістрів
popax
ret ; повернення до викликаючої програми
ENDP StrLength
; -------------------------------------------------------------------------------------------
; StrWrite вивід рядка на стандартний пристрій виводу
; StrWrite2 вивід заданої кількості символів рядка на консоль
; -------------------------------------------------------------------------------------------
; Вхід di адреса ASCIIрядка
; cx кількість записуваних символів (для StrWrite2)
; Вихід символьний рядок виводиться на стандартний пристрій
; виводу
Регістри cx(для StrWrite)
; -------------------------------------------------------------------------------------------
PROCStrWrite
callStrLength ; встановити в cxдовжину рядка
PROCStrWrite2 ; друга змінна точка входу
pushax ; збереження змінюваних регістрів
pushbx
pushdx
mov bx, 1 ; задання стандартного пристрою виводу
mov dx, di ; адресація ASCIIрядка в ds:dx
movah, 40h ; в axномер функції, що виконує запис
; в файл або на пристрій виводу
int 21h ; виклик 21 переривання DOS
popdx ; відновлення збережених регістрів
popbx ; із стеку
popax
ret ; повернення до визиваючої програми
ENDP StrWrite2
ENDP StrWrite
; -------------------------------------------------------------------------------------------
; NewLine перейти на новий рядок на стандартному пристрої виводу
; -------------------------------------------------------------------------------------------
; Вхід не має
; Вихід на пристрій виводу посилаються символи повернення
; каретки і прогону рядка
; Регістри не має
; -------------------------------------------------------------------------------------------
PROCNewLine
pushax ; збереження регістрів у стек
pushdx
movah, 2 ; в ahномер функції виводу символу у DOS
mov dl, ASCcr ; в dlсимвол повернення каретки
int 21h ; вивести символ повернення каретки
mov dl, ASClf ; в dlсимвол прогону рядку
int 21h ; вивести символ прогону рядку
pop dx ; відновлення регістрів із стеку
pop ax
ret ; повернення до викликаючої програми
ENDP NewLine
; -------------------------------------------------------------------------------------------
; WriteSimv вивід на стандартний пристрій виводу заданий символ
; визначену кількість разів
; -------------------------------------------------------------------------------------------
; Вхід dl код символу
; cx кількість виводів символу
; Вихід на пристрій виводу задану кількість разів посилається
; переданий символ
;Регістри не має
; -------------------------------------------------------------------------------------------
PROCWriteSimv
pushax ; збереження регістрів
pushcx
@@01:
mov ah,02 ; в ahномер функції DOSзапису символу
int 21h ; вивести заданий символ
loop @@01 ; повторювати доки cx≠0
popcx ; відновлення регістрів
popax
ret ; повернення до викликаючої програми
ENDP WriteSimv
END
Функції, надані програмним модулем STRIO.asm, є зручними і простими інструментами виводу інформації на стандартний пристрій виводу і будуть використані в основній програмі.
3.1.3. Модуль BINASC.asm
Мови високого рівня надають програмісту можливість безпосередньо зчитувати і виводити числові значення. Нажаль, мова асемблера таких інструментів не має. В основній програмі значна частина роботи пов’язана з виводом із деякого буфера даних на екран . Однак дані в буфері зберігаються у вигляді двійкових слів того чи іншого типу. З'являється необхідність перетворення двійкових даних у ASCII-рядки, щоб у подальшому їх можна було вивести на екран. Дану проблему і покликані вирішити функції модуля BINASC.asm. Модуль складається із чотирьох функцій: допоміжних функцій HexDigit(перетворення чотирьохбітового значення у ASCII-цифру) і NumToAscii(перетворення беззнакового двійкового числа у ASCII-рядок), а також двох функцій BinToAscHexі BinToAscDec, які встановлюють систему числення і викликають вищезгадані функції.
Слід зазначити, що функція BinToAscDecзручна для перетворення і подальшого виводу чисел типу "слово" у вигляді десяткового числа.
Функцію BinToAscHexможна використовувати для виводу подвійного слова у вигляді шістнадцятирічного числа, послідовно перетворюючи і виводячи спочатку молодші два, а потім і старші байти, на екран.
Це дозволяє вирішити проблему обробки чотирьохбайтових даних, оскільки звичайні регістри є двохбайтовими і перетворення такого числа у, наприклад, десяткове представлення є проблематичним.
Код програмного модуля BINASC.asmприведено нижче:
IDEAL
MODEL small
ASCnull EQU 0 ; нульовий ASCII-символ
DATASEG
CODESEG
PUBLIC HexDigit, NumToAscii
PUBLIC BinToAscHex, BinToAscDec
; -------------------------------------------------------------------------------------------
; HexDigit перетворює чотирьохбітове значення в ASCII-цифру
; -------------------------------------------------------------------------------------------
; Вхід dlзначення від 0 до 15
; Вихід dl шістнадцятирічний еквівалент ASCII-цифри
; Регістри dl
; -------------------------------------------------------------------------------------------
PROCHexDigit
cmpdl, 10 ; перевірка, чи є dl< 10
; (тобто менше шістнадцятирічного 'А')
jb @@10 ; якщо так, то перехід
add dl, 'A'-10 ; перетворити в A, B, C, D, EабоF
ret ; повернення до викликаючої програми
@@10:
or dl, '0' ; перетворити в числа від 0 до 9
ret ; повернення до викликаючої програми
ENDP HexDigit
; -------------------------------------------------------------------------------------------
; NumToAscii перетворює беззнакове двійкове значення у ASCII-рядок
; згідно із заданою системою числення
; -------------------------------------------------------------------------------------------
; Вхід ax двохбайтове число, яке перетворюється
; bx основа системи числення результату (2 – двійкова,
; 10 – десяткова, 16 – шістнадцятирічна)
; cx мінімальна кількість цифр, що виводяться
; di адреса рядка для результату
; Вихід di вказує на новостворений рядок із результатом
; Регістри не має
; -------------------------------------------------------------------------------------------
PROCNumToASCII
pushdx ; збереження змінюваних регістрів
pushdi
push si
xor si, si ; встановити лічильник цифр у стеку в 0
jcxz @@20 ; якщо cx= 0, то перехід
@@10:
xor dx, dx ; обнуління dx; axрозширюється до
; 32-х-бітногоdxax
div bx ; в axрезультат ділення на bx, в dxзалишок
call HexDigit ; перетворення числа в dlв ASCII-пару
push dx ; збереження цифри в стеку
inc si ; збільшення лічильника цифр у стеку
loop @@10 ; виконувати цикл, доки не оброблена
; мінімальна кількість цифр
@@20:
inc cx ; встановити cx=1, якщо не усі цифри
; оброблені
or ax, ax ; перевірка axна обробку всіх цифр
jnz @@10 ; якщо ax≠a, продовження перетворень
mov cx, si ; в cxпоміщується кількість цифр у стеку
jcxz @@40 ; пропуск наступного циклу, якщо cx=0
cld ; автоматичне збільшення di
@@30:
pop ax ; в axпоміщується цифра із стеку
stosb ; запис цифри в рядок і збільшення di
loop @@30 ; в циклі вивід cxцифр
@@40:
mov [byte di], ASCnull ; записується 0 у кінець рядка
popsi ; відновлення регістрів
popdi
popdx
ret ; повернення до викликаючої програми
ENDPNumToASCII
; -------------------------------------------------------------------------------------------
; BinToAscHex перетворює двійкове значення в шістнадцятирічні
; ASCII-рядки
; -------------------------------------------------------------------------------------------
; Вхід axдвохбайтове значення, що перетворюється
; cx мінімальна кількість чисел, що виводиться
; diадреса рядка для результату
; Вихід di вказує на рядок із сформованим результатом
; Регістри не має
; -------------------------------------------------------------------------------------------
PROCBinToAscHex
movbx, 16 ; в bxвстановити основу шістнадцятирічної
; системи числення - 16
callNumToAscii ; перетворення числа із axв ASCII-рядок,
; на який вказує di
ret ; повернення до викликаючої програми
ENDPBinToAscHex
; -------------------------------------------------------------------------------------------
; BinToAscHex перетворює двійкове значення в десяткові ASCII-рядки
; -------------------------------------------------------------------------------------------
; Вхід axдвохбайтове значення, що перетворюється
; cx мінімальна кількість чисел, що виводиться
; diадреса рядка для результату
; Вихід di вказує на рядок із сформованим результатом
; Регістри не має
; -------------------------------------------------------------------------------------------
PROC BinToAscDec
mov bx, 10 ; в bxвстановити основу десяткової
; системи числення – 10
callNumToAscii ; перетворення числа із axв ASCII-рядок,
; на який вказує di
ret ; повернення до викликаючої програми
ENDPBinToAscDec
END
Таким чином програмний модуль BINASC.asmдає нам спеціальні функції, що дозволяють перетворити і вивести на екран дані із DTA, що описують файли.
3.2. Розробка основної програми DR.asm
Модулі PARAMS.asm, STRIO.asmі BINASC.asmскладають функціональну базу програмних інструментів для розробки основної програми. Згідно із поставленою задачею, програма має знаходити файли, задані маскою, копіювати DTA, що їх описує, у власний буфер, обробляти отримані дані і виводити необхідну інформацію на екран, а потім переходити до наступного файлу, що відповідає масці, доки не обробить всі.
Таким чином задачу можна розбити на 3 частини:
1) Отримання конфігураційних даних із консолі і, при їх відсутності, встановлення стандартної маски файлів;
2) Пошук файлів, що відповідають масці, і заповнення внутрішнього буферу їх DTA(процедура DirEgine);
3) Саме обробка DTA, вивід даних на екран (процедура Action).
Спираючись на викладені міркування, було створено основну програму DR.asm:
IDEAL
MODEL small
STACK 256
FileName EQU 30 ; зміщення імені файлу в буфері dirData
DATASEG
exCode DB 0 ; код виходу
defaultSpec DB '*.*', 0 ; стандартній ASCII-шаблон маски
DTAsegDW ? ; сегмент для DTA
DTAofsDW ? ; зміщення для DTA
dirDataDB 43 DUP(?) ; буфер для запису вмісту каталогу
bufferDB 6 DUP(?) ; буфер для збереження проміжних
; ASCII-рядків
pointDB ' * ',0 ; ASCII-шаблон зірочки
tit1 DB 'The DIRWUER wersion 1.0',10,13,'Romanov Alexander Urievich. KIT-13A NTU"KhPI"',10,13,'Copyright (C) 2005 byRomanovAlexander',0 ; інформація о програмі
tablDB 'FilenameOnRSkrSysTomKatArhTime
DataSize',0 ; заголовок таблиці
CODESEG
EXTRNGetParams:Proc, GetOneParam:Proc, ParamCount:Proc
із params.obj
EXTRNStrLength:Proc, StrWrite:Proc
EXTRNNewLine:Proc, WriteSimv:Proc, StrWrite2:Proc
; із strio.obj
EXTRNBinToAscHex:Proc, BinToAscDec:Proc
; із Binasc.obj
Start:
movax, @data ; встановлює в axадресу сегмента даних
mov es, ax ; встановлює в esадресу сегмента даних
; ------Отримання даних із командного рядка
call GetParams ; отримати параметри із командного рядка