Реферат по предмету "Информатика"


Вивід вмісту каталогу y середовищі MS DOS

--PAGE_BREAK--; Регістри                      не змінюються
; —
PROC Separators
push  ax                                 ; збереження у стеку ax
mov  al, [si]                           ; в al поміщується символ із ds:si
cmp   al, 020h                        ; порівняння al із пробілом
je       @@10                          ; якщо так, то перехід
cmp   al, 009h                        ; порівняння al із табуляцією
je       @@10                          ; якщо так, то перехід
cmp   al, 00Dh                       ; порівняння al із символом повернення
; каретки
@@10:
pop ax                                   ; відновлення ax
ret                                          ; повернення до викликаючої програми
ENDP Separators
; —
; ParamCount                         повертає кількість параметрів у хвості команди
; —
; Вхід                                     не має
; Вихід                 CX             кількість параметрів командного рядка
; Регістри            CX
; —
PROC ParamCount
mov  cx, [numParams]; отримати значення змінної numParams
ret                                ; повернення до викликаючої програми
ENDP ParamCount
; —
; GetParams                  занесення параметрів командного рядка DOS у буфер
; —
; Вхід         ds      префікс сегмента програми (PSP) (адресує PSP, якщо його
;                           не змінювали)
;                  es      сегмент даних програми
; Вихід       [params]     початок буфера заповненого даними
;                  [numParams]       кількість параметрів
;                  ds      сегмент даних програми
; Регістри   al, bx, dx, si, di, ds
; —
PROC GetParams
;------Ініціалізація cx і індексних регістрів si і di
push  ax                                 ; збереження регістрів
push bx
push dx
push si
push di
xor    ch, ch                                     ; обнуління верхньої половини cx
mov  cl, [ds:TailLen]             ; в cx довжина параметрів
inc     cx                                 ; включити символ повернення каретки
mov  si, CommandTail         ; адреса параметрів поміщується в si
mov  di, offset params          ; адреса призначення поміщується в di
; ------Пропуск початкових пробілів і табуляції
@@10:
call    Separators                   ; пропуск пробілів і табуляції
jne     @@20                          ; перехід, якщо пробілів і табуляції не має
inc     si                                  ; пропуск символу
loop  @@10                          ; цикл, доки не скінчиться обробка, або cx=0
; ------Копіювання параметрів рядка в буфер params
@@20:
push  cx                                 ; збереження cx у стеку
jcxz   @@30                          ; пропуск копіювання, якщо cx=0
cld                                         ; збільшення на 1 si і di
rep    movsb                          ; копіювання cx байтів із ds:si в es:di
; ------Перетворення пробілів в 0 і встановлення numParams
@@30:
push  es
pop   ds                                 ; ds = es
pop   cx                                 ; відновлення cx (довжину)
xor    bx, bx                                    ; обнуління bx, лічильник параметрів
jcxz   @@60                          ; пропуск циклу якщо cx=0 (довжина)
mov  si, offset params          ; поміщення адреси параметрів в si
@@40:
call    Separators                   ; перевірка на пробіли, табуляцію,
                                              ; повернення каретки
jne     @@50                          ; перехід, якщо не знайдено роздільник
mov  [byte ptr si], 0              ; заміна роздільника на 0
inc     bx                                 ; збільшення лічильника кількості
; параметрів
@@50:
inc     si                                  ; переміщення указника на наступний
; символ
loop  @@40                          ; виконувати в циклі, доки cx ≠ 0
@@60:
mov  [numParams], bx         ; збереження в numParams кількість
; параметрів
pop   ax                                 ; відновлення регістрів
pop bx
pop dx
pop si
pop di
ret                                          ; повернення до батьківської програми
ENDP GetParams
; —
; GetOneParam    отримати адресу параметра за номером
; —
; Вхід                   cx      номер параметра (має бути менше значення в numParams)
; Вихід       di      зміщення ASCII рядка із потрібним параметром
; Регістри   di     
; —
PROC GetOneParam
push  ax                                 ; збереження регістрів ax і cx
push  cx
xor    al, al                             ; обнуління al (ініціалізація шуканого
; значення 0)
mov  di, offset params          ; адреса параметрів рядка
jcxz @@99                            ; якщо номер параметра (cx) дорівнює 0,
; то вихід
cmp   cx, [numParams]          ; порівняння cx із кількістю параметрів
jae     @@99                          ; вихід, якщо передано неіснуючого
; параметру
cld                                         ; автоматичне збільшення di
@@10:
scasb                                     ; пошук нульового обмежувача
jnz     @@10                          ; повтор, доки не знайдено 0
loop  @@10                          ; повтор, доки в cx не буде 0
@@99:
pop   cx                                 ; відновлення регістрів cx, ax
pop   ax
ret                                          ; повернення до викликаючої програми
ENDP GetOneParam
END
Таким чином, програмний модуль PARAMS.asm є зручним інструментом для реалізації роботи із командним рядком і буде використаний в основній програмі.
3.1.2. Модуль STRIO.asm
Оскільки важливою частиною основної програми, згідно із завданням, буде вивід текстових рядків на екран, то є необхідність у створенні спеціального програмного модуля, який би містив процедури для обробки і виводу ASCII рядків на екран. Пряме використання функцій DOS в основній програмі є незручним, оскільки є потреба у спрощенні коду для його сприйняття.
З цих міркувань було розроблено програмний модуль STRIO.asm, в якому міститься п’ять спеціальних функцій: StrLength (визначає кількість символів, записаних в ASCII рядку), дві функції виводу ASCII-рядків на екран – StrWrite і StrWrite2, а також функцію NewLine (перехід на новий рядок) та WriteSimv (виводить на екран заданий символ необхідну кількість разів).
Слід зазначити, що даний програмний модуль не містить функцій читання із консолі в рядок, однак основна програма отримує дані із PSP DOS-а і опрацьовує вже створені дані, а тому не потребує якихось додаткових вказівок через консоль від користувача, всі необхідні специфічні дані (наприклад, маска файлів) користувач може задати в командному рядку при визові основної програми.
Код програмного модуля STRIO.ASM приведений нижче:
IDEAL
MODEL small
ASCnull     EQU           0                ; ASCII нуль
ASCcr                  EQU           13    ; ASCII символ повернення каретки
ASClf                  EQU           10    ; ASCII символ вертикальної табуляції
; (прогону рядка)
CODESEG
PUBLIC StrLength, StrWrite, StrWrite2, NewLine, WriteSimv
; —
; StrLength                    підраховує кількість ненульових символів в рядку
; —
; Вхід                  di      адреса ASCII рядка
; Вихід       cx      кількість ненульових символів в рядку
; Регістри   cx     
; —
PROC StrLength
push  ax                                 ; зберегти у стеку змінювані
push di                                  ; регістри ax, di
xor    al, al                             ; в al поміщується шуканий символ 0
mov cx, 0ffffh                      ; в cx максимальна глибина пошуку
cld                                         ; автоматичне збільшення di
repnz scasb                                    ; шукати al, доки [di] або cx не стане 0
not    cx                                 ; логічне заперечення cx
dec    cx                                 ; зменшення cx на 1 – довжина рядка
pop   di                                  ; відновлення регістрів
pop   ax
ret                                          ; повернення до викликаючої програми
ENDP StrLength
; —
; StrWrite             вивід рядка на стандартний пристрій виводу
; StrWrite2           вивід заданої кількості символів рядка на консоль
; —
; Вхід                   di      адреса ASCII рядка
;                  cx      кількість записуваних символів (для StrWrite2)
; Вихід                 символьний рядок виводиться на стандартний пристрій
;                           виводу
Регістри     cx      (для StrWrite)
; —
PROC StrWrite
call    StrLength                     ; встановити в cx довжину рядка
PROC StrWrite2                             ; друга змінна точка входу
push  ax                                 ; збереження змінюваних регістрів
push  bx
push  dx
mov  bx, 1                             ; задання стандартного пристрою виводу
mov  dx, di                            ; адресація ASCII рядка в ds:dx
mov  ah, 40h                         ; в ax номер функції, що виконує запис
; в файл або на пристрій виводу
int     21h                               ; виклик 21 переривання DOS
pop   dx                                 ; відновлення збережених регістрів
pop   bx                                 ; із стеку
pop   ax
ret                                          ; повернення до визиваючої програми
ENDP StrWrite2
ENDP StrWrite
; —
; NewLine            перейти на новий рядок на стандартному пристрої виводу
; —
; Вхід                   не має
; Вихід                 на пристрій виводу посилаються символи повернення
;                           каретки і прогону рядка
; Регістри            не має
; —
PROC NewLine
push  ax                                 ; збереження регістрів у стек
push  dx
mov  ah, 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      кількість виводів символу
; Вихід                 на пристрій виводу задану кількість разів посилається
;                           переданий символ
; Регістри             не має
; —
PROC WriteSimv
push  ax                                 ; збереження регістрів
push  cx
@@01:
mov  ah,02                            ; в ah номер функції DOS запису символу
int     21h                               ; вивести заданий символ
loop @@01                          ; повторювати доки cx≠0
pop   cx                                 ; відновлення регістрів
pop   ax
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     
; —
PROC HexDigit
cmp   dl, 10                            ; перевірка, чи є dl
; (тобто менше шістнадцятирічного 'А')
jb      @@10                          ; якщо так, то перехід
add    dl, 'A'-10                      ; перетворити в A, B, C, D, E або F
ret                                          ; повернення до викликаючої програми
@@10:
or      dl, '0'                            ; перетворити в числа від 0 до 9
ret                                          ; повернення до викликаючої програми
ENDP HexDigit
; —
; NumToAscii      перетворює беззнакове двійкове значення у ASCII-рядок
;                           згідно із заданою системою числення
; —
    продолжение
--PAGE_BREAK--; Вхід                   ax      двохбайтове число, яке перетворюється
;                  bx     основа системи числення результату (2 – двійкова,
;                           10 – десяткова, 16 – шістнадцятирічна)
;                  cx      мінімальна кількість цифр, що виводяться
;                  di      адреса рядка для результату
; Вихід       di      вказує на новостворений рядок із результатом
; Регістри            не має
; —
PROC NumToASCII
push  dx                                 ; збереження змінюваних регістрів
push  di
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 у кінець рядка
pop   si                                  ; відновлення регістрів
pop   di
pop   dx
ret                                          ; повернення до викликаючої програми
ENDP NumToASCII
; —
; BinTo AscHex   перетворює двійкове значення в шістнадцятирічні
;                           ASCII-рядки
; —
; Вхід                   ax      двохбайтове значення, що перетворюється
;                  cx      мінімальна кількість чисел, що виводиться
;                  di      адреса рядка для результату
; Вихід       di      вказує на рядок із сформованим результатом
; Регістри            не має
; —
PROC BinToAscHex
mov  bx, 16                                    ; в bx встановити основу шістнадцятирічної
; системи числення — 16
call    NumToAscii                ; перетворення числа із ax в ASCII-рядок,
; на який вказує di
ret                                          ; повернення до викликаючої програми
ENDP BinToAscHex
; —
; BinTo AscHex   перетворює двійкове значення в десяткові ASCII-рядки
; —
; Вхід                   ax      двохбайтове значення, що перетворюється
;                  cx      мінімальна кількість чисел, що виводиться
;                  di      адреса рядка для результату
; Вихід       di      вказує на рядок із сформованим результатом
; Регістри            не має
; —
PROC BinToAscDec
mov  bx, 10                                    ; в bx встановити основу десяткової
; системи числення – 10
call    NumToAscii                ; перетворення числа із ax в ASCII-рядок,
; на який вказує di
ret                                          ; повернення до викликаючої програми
ENDP BinToAscDec                      
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-шаблон маски
DTAseg               DW   ?                ; сегмент для DTA
DTAofs               DW   ?                ; зміщення для DTA
dirData                DB    43 DUP (?); буфер для запису вмісту каталогу
buffer                            DB    6 DUP (?)  ; буфер для збереження проміжних
; ASCII-рядків
point                    DB    ' * ',0         ; ASCII-шаблон зірочки
tit1                      DB    'The DIRWUER wersion 1.0',10,13, 'Romanov Alexander Urievich. KIT-13A NTU«KhPI»',10,13,'Copyright (C) 2005 by Romanov Alexander',0                                ; інформація о програмі
tabl                      DB    'Filename    OnR Skr Sys Tom Kat Arh Time
Data                     Size',0                 ; заголовок таблиці
CODESEG
EXTRN GetParams:Proc, GetOneParam:Proc, ParamCount:Proc
 із params.obj
EXTRN StrLength:Proc, StrWrite:Proc
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
    продолжение
--PAGE_BREAK--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.
Наступним кроком реалізується вивід атрибутів файлу шляхом виводу зірочок навпроти відповідного атрибуту. Байт атрибуту файлу має наступну структуру [6]:
Тобто, якщо біт атрибуту файлу буде мати наступне значення 21h, це означатиме, що файл є архівним, він лише для читання.
Передостаннім кроком виводяться час і дата створення файлу у форматі: година: хвилина: секунда день\місяць\рік. Дані, що описують час і дату створення/змінення файлу, потребують накладання масок і здвигів для
№ біта
Операція
№ біта
Операція
Час створення
Дата створення
15
година
(0-23)
(t & 0f800h)>>11
15
рік
(0-119)+1980
d & 001fh
14
14
13
13
12
12
11
11
10
хвилина
(0-59)
(t & 07e0h)>>5
10
9
9
8
8
місяць
(1-12)
(d & 01e0h)>>5
7
7
6
6
5
5
4
секунда / 2
(0-30)
t & 001fh
4
день
(0-31)
(d & f800h)>>9
3
3
2
2
1
1
0
0
отримання необхідної інформації і представлені в наступному виді [6]:
Перевід двійкових чисел у ASCII-десяткове представлення для виводу на екран реалізується за допомогою функції BinToAscDec модуля BINASC.obj.
Останній крок виводу розміру файлу виконується в два етапи, оскільки розмір файлу міститься у подвійному слові і модуль BSNASC.obj не надає інструменту для переведення двійкових даних у ASCII-рядок.
Спочатку за допомогою функції BinToAscHex модуля BINASC.obj переводиться молодші, а потім старші два байти, переведені у ASCII-шістнадцятирічне представлення.
По завершенні своєї роботи Action знов передає керування викликаючій функції DirEngin, яка повторює пошук файлів і викликає для роботи Action, доки не завершить обробку всіх файлів, що відповідають масці. Після цього DirEngine повертає старий DTA і передає курування основній програмі, яка завершує роботу і повертає код виходу.
Результати роботи програми:
D:\Program\ASM\misk>dr
The DIRWUER wersion 1.0
Romanov Alexander Urievich. KIT-13A NTU«KhPI»
Copyright (C) 2005 by Romanov Alexander
Filename OnR Skr Sys Tom Kat Arh Time Data Size
. * 11:59:18 11\5 \2005 00
… * 11:59:18 11\5 \2005 00
BLW32.DLL * 12:12:0 14\5 \1996 52020
DEBUG.EXE * * 22:22:0 5 \5 \1999 0518A
USA.BLL * 12:12:0 14\5 \1996 18DCD
MYREP.CBA * 18:48:42 25\1 \2002 01F
DIRECT * 12:27:54 11\5 \2005 00
CATALOG3.CAB * * 22:22:0 5 \5 \1999 425C3
SUHELPER.BIN * * 22:22:0 5 \5 \1999 05C0
SAVE32.COM * * 22:22:0 5 \5 \1999 0398
ASD.LOG * * 13:8 :20 11\8 \2004 0162
IO.SYS * * * 22:22:0 5 \5 \1999 364B6
MSDOS.SYS * * * * 18:30:28 16\7 \2004 0697
08-APRIL.MP3 * 11:42:44 7 \12\2003 B11100
DR.EXE * 12:14:28 11\5 \2005 05A1
DR.BAT * 12:54:34 4 \5 \2005 09B
D:\Program\ASM\misk>dr.exe *.exe
The DIRWUER wersion 1.0
Romanov Alexander Urievich. KIT-13A NTU«KhPI»
Copyright (C) 2005 by Romanov Alexander
Filename OnR Skr Sys Tom Kat Arh Time Data Size
DEBUG.EXE * * 22:22:0 5 \5 \1999 0518A
DR.EXE * 12:14:28 11\5 \2005 05A1
D:\Program\ASM\misk>dr s*.???
The DIRWUER wersion 1.0
Romanov Alexander Urievich. KIT-13A NTU«KhPI»
Copyright (C) 2005 by Romanov Alexander
Filename OnR Skr Sys Tom Kat Arh Time Data Size
SUHELPER.BIN * * 22:22:0 5 \5 \1999 05C0
SAVE32.COM * * 22:22:0 5 \5 \1999 0398
D:\Program\ASM\misk>dr d:\program\asm\misk\direct\*.*
The DIRWUER wersion 1.0
Romanov Alexander Urievich. KIT-13A NTU«KhPI»
Copyright (C) 2005 by Romanov Alexander
Filename OnR Skr Sys Tom Kat Arh Time Data Size
. * 12:27:54 11\5 \2005 00
… * 12:27:54 11\5 \2005 00
BINASC.ASM * 11:3 :40 8 \5 \2005 0300
PARAMS.ASM * 13:31:20 6 \5 \2005 04E4
TD.EXE * 14:39:40 24\12\2002 784F0
Як видно із приведених результатів програма DR.EXE за умовчанням виводить весь вміст директорії, в якій вона розташована (приклад 1). Інші приклади демонструють різноманітні засоби виклику програми із заданням різноманітних масок, використовуючи символи "*" і "?". Останній приклад демонструє, що виклик DR.exe можна реалізувати і з маскою, що задає повний шлях до директорії, інформацію про яку необхідно вивести.
Таким чином, розроблена програма DR.exe повністю відповідає поставленому завданню про створення програми мовою асемблера, яка виводить вміст директорії, атрибути, розмір і час/дату створення файлів і папок, які в ній містяться.
4. Розробка задачі на мові високого рівня із використанням асемблерних фрагментів коду
Як показала третя глава, розробка програми чисто на асемблері є складним процесом і потребує розробки супутніх (допоміжних) модулів для реалізації моментів, що не пов’язані із основним алгоритмом задачі (таких, як вивід на екран, перетворення двійкових даних у ASCII-рядки, тощо). Мови високого рівня дають можливість реалізувати все автоматично [3]. Такий стан речей спонукає розробити програму, в якій основний алгоритм пошуку DTA і необхідних файлів, що відповідають масці, реалізовані асемблерними вставками, а задачі, пов’язані із розробкою інтерфейсу і виводу даних на екран, реалізовані, наприклад, мовою Pascal.
4.1. Розробка програми на Pascal
Мова Pascal дає можливість створити вказівник типу «запис» (поля «запису» описують атрибут, час, дату, розмір і ім'я файлу) прямо на стандартний буфер DTA, не створюючи власного і не виконуючи зайвих дій по встановленню нової адреси буфера DTA і відновлення старої після завершення програми. Вивід інформації про файл довіряється процедурі, яка обробляє поля вказівника на DTA і виводить дані стандартними функціями Pascal.
На початку програми є сенс запитувати користувача про бажання задати власну маску для файлів, або лишити стандартну ("*.*").
Згідно із зазначеними змінами було розроблено програму DIRWUER.pas, приведену нижче:
{DIRWUER.pas}
Uses crt;
{------FindFirst – шукає перше входження файлу, що відповідає заданій масці}
Function FindFirst (Path: PChar): Boolean; assembler;
asm
mov ah, 4Eh                           {в ah номер функції першого пошуку}
mov cx, 3fh                                      {в cx маска для всіх атрибутів файлу}
mov dx, word ptr Path           {dx вказує на маску файлу}
int 21h                                    {виклик функції першого пошуку файлу}
mov al, 0                                {в al поміщується 0 – код помилки (false)}
jc @Failed                              {якщо помилка, повернути код помилки,}
inc al                                       {інакше повернути 1 – true }
@Failed:
end;
{------FindNext шукає наступне входження файлів, маска і атрибути яких були задані при попередньому пошуку.}
Function FindNext: Boolean; assembler;
asm
mov ah, 4Fh                                    {в ah номер функції наступного пошуку }
                                               {файлу}
int 21h                                    {пошук наступного файлу за параметром,}
                                               {заданим функцією 4Eh}
mov al, 0                                {в al поміщується 0 – код помилки (false)}
jc @Failed                              {повернути код помилки, якщо помилка}
inc al                                       {інакше повернути 1 – true }
@Failed:
end;
Type
DTA = record                         {запис описує структуру DTA-буфера}
         Reserved: Array[0..$14] of Byte;    {резервна область пам'яті}
         Attrib        : Byte;                                    {поле атрибуту}
         Time: Word;                                  {поле часу створення}
         Date : Word;                                  {поле дати}
         Size  : Longint;                               {розмір}
         Name         : Array[0..$C] of Char;                   {ім'я файлу із розширенням}
         end;
PDTA = ^DTA;                      {вказівник на буфер DTA}
{------GetDTAAddress повертає адресу буфера DTA}
Function GetDTAAddress: PDTA; assembler;
asm
mov ah, 2Fh                                    {в ah номер функції пошуку DTA}
int 21h                                    {отримання в as:bx адреси DTA }
push es                                   {в dx через стек передаються дані із es}
pop dx                                   
mov ax, bx                             {передача в ax даних із bx}
{в dx:ax повертається результат}
end;
Var
DTAAddress      : PDTA;
         s                : string;
Path                    : PChar;
         i                 : byte;
Label          1;
{------Процедура виводу даних о файлі/директорії згідно із інформацією в DTA}
Procedure ShowEntry;
Begin
Write(DTAAddress^.Name:13,' ');   {вивід імені файлу із розширенням}
for i: = 0 to 5 do
if (DTAAddress^.Attrib and (1 shl i)) 0
then write(' * ')     {вивід зірочок навпроти файлів }
else write(' ');       {із відповідними атрибутами}
{------Вивід часу створення файлу}
Write(' ',((DTAAddress^.Time and $0f800)shr 11):2);
Write(':',((DTAAddress^.Time and $07e0)shr 5):2,':');
Write(((DTAAddress^.Time and $1f)shl 1):2);
{------Вивід дати створення файлу}
Write(' ',(DTAAddress^.Date and $1f):2,'/');
Write(((DTAAddress^.Date and $01e0)shr 5):2,'/');
Write((((DTAAddress^.Date and $0f800)shr 9)+$07bc):4);
Writeln(' ',DTAAddress^.Size:7);    {вивід розміру файлу}
end;
BEGIN
ClrScr;                                                       {очистка екрану}
{------Вивід інформації о програмі}
Writeln('The DIRWUER wersion 1.0');
Writeln('Romanov Alexander Urievich. KIT-13A KHPI');
    продолжение
--PAGE_BREAK--


Не сдавайте скачаную работу преподавателю!
Данный реферат Вы можете использовать для подготовки курсовых проектов.

Поделись с друзьями, за репост + 100 мильонов к студенческой карме :

Пишем реферат самостоятельно:
! Как писать рефераты
Практические рекомендации по написанию студенческих рефератов.
! План реферата Краткий список разделов, отражающий структура и порядок работы над будующим рефератом.
! Введение реферата Вводная часть работы, в которой отражается цель и обозначается список задач.
! Заключение реферата В заключении подводятся итоги, описывается была ли достигнута поставленная цель, каковы результаты.
! Оформление рефератов Методические рекомендации по грамотному оформлению работы по ГОСТ.

Читайте также:
Виды рефератов Какими бывают рефераты по своему назначению и структуре.