Інтерпретатор функцій DOS: DATE, TIME, DIR, CD, MD, RD

Розробка програми-інтерпретатора функцій командного процесора DOS: TIME, DATE, DIR, CD, MD, RD на мові Асемблера. Функціональні модулі, процедури та макроси, які використовуються в програмі. Опис алгоритму розв’язання задачі, його програмна реалізація.

Рубрика Программирование, компьютеры и кибернетика
Вид курсовая работа
Язык украинский
Дата добавления 26.04.2016
Размер файла 42,6 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

Размещено на http://www.allbest.ru/

1

Размещено на http://www.allbest.ru/

Міністерство освіти і науки України

Тернопільська академія народного господарства

Інститут комп'ютерних інформаційних технологій

Кафедра спеціалізованих комп'ютерних систем

Курсова робота

з дисципліни «Системне програмування»

на тему:

Інтерпретатор функцій DOS: DATE, TIME, DIR, CD, MD, RD

Виконав: Стахов Євген

студент групи. КСМ-21

Перевірив: к.т.н. Сегін А.І.

м. Тернопіль - 2003 р.

ЗАВДАННЯ НА КУРСОВИЙ ПРОЕКТ

Група КСМ-21

Студент Стахов Євген Валерійович

Тема курсового проекту: Інтерпретатор функцій DOS: DATE, TIME, DIR, CD, MD, RD

Основні розділи:

1. Опис алгоритму розв'язання задачі

2. Програмна реалізація алгоритму

3. Тестування програми

Графічна частина:

1. Блок-схема програми

Рекомендована література:

1. Абель П. Язык Ассемблера для IBM PC и программирования: Пер. с англ. - М.: Высшая школа, 1992

2. Юров В., Хорошенко С. Assembler: учебный курс - СПБ: Издательство

"Питер", 1999

ЗМІСТ

  • Вступ
  • Розділ 1. Опис алгоритму розв'язання задачі
  • Розділ 2. Програмна реалізація алгоритму
    • 2.1 Функції, які використовуються в програмі
    • 2.2 Процедури, які використовуються в програмі
    • 2.3 Макроси, які використовуються в програмі
  • Розділ 3 Тестування програми
  • Висновки
  • Список використаної літератури
  • Додаток А. Лістинг програми
  • Додаток Б. Блок-схема програми

ВСТУП

Розповсюдження мікропроцесорів стало причиною перегляду ставлення до мови Асемблера. Це відбулось із-за двох основних причин: програми, написані на мові Асемблера потребують значно менше пам'яті та часу виконання; знання мови Асемблера і розуміння результуючого машинного коду дає розуміння архітектури машини, що неможливо досягти користуючись мовами вищого рівня. Навіть незважаючи на величезну швидкодію сучасних комп'ютерів, при написанні програм, що пов'язані з використанням графіки, значна частина коду пишеться на мові Асемблера.

У даному курсовому проекті необхідно розробити програму на мові Асемблера, яка реалізує функції командного процесора DATE, TIME, DIR, CD, MK, RD. Тобто програма повинна виводити поточну дату і час, змінювати їх, виводити список файлів та піддиректорій вказаної директорії, змінювати поточну директорію, створювати та видаляти каталог. Під час створення або видалення каталогу вносяться зміни в таблицю розміщення файлів (FAT) для того щоб сектори, які використовуються цим підкаталогом були доступні іншим файлам.

Для написання даного курсового проекту я використовував компілятор Turbo Assembler 3.2 та програму Turbo Link 3.0 для лінкування. Для відладки коду я використовував Turbo Debugger v.3.1.

Розділ 1. Опис алгоритму розв'язання задачі

Аналізуючи завдання курсового проекту, я вирішив використати метод програмування, який передбачає розбиття програми на окремі функціональні модулі, які потім викликаються з основної програми в процесі її роботи. Це значно спрощує читання програми і дозволяє використовувати одні і ті ж функції кілька разів.

В основі розробки такої програми лежить низхідне програмування - тобто спочатку розробляється основна програма. В даному випадку розроблялася програма, яка зчитувала з клавіатури символи та обробляла їх. При введенні тої чи іншої команди викликалася відповідна функція, але на початковому етапі розробки програми замість цих підпрограм були „заглушки” - прості підпрограми, які або нічого не виконували, або виводили на екран повідомлення, яке свідчило про правильну роботу основної програми. По мірі подальшої розробки ці „заглушки” замінялися програмами, які виконували вже конкретну функцію. Для того щоб визначити яку команду ввів користувач, я склав алгоритм. Кожна команда може мати не більше 4 символів. Тому для цього можна використати регістр EAX. Завантажуємо в цей регістр символи таким чином:

lea si, Command

lodsw

xchg al, ah

shl eax, 16

lodsw

xchg al, ah

Наприклад розберемо команду EXIT. Команда LODSW завантажить в регістр AX символи в зворотному порядку ("XE"). Тому потрібно поміняти їх місцями. Після цього зсовуємо вліво на 16 біт (записуємо їх в розширену частину) і завантажуємо наступні 2 символи. Тепер регістр EAX містить "EXIT". Якщо команда має менше символів, то в старші біти записуються 0.

Розділ 2. Програмна реалізація алгоритму

2.1 Функції, які використовуються в програмі

Основне переривання, яке використовується в програмі, це переривання int 21h (переривання DOS). В програмі використовуються такі функції цього переривання [1-2]:

функція 9h - вивести строку на дисплей

Вхідні параметри:

AH = 9h

DS:DX = адреса строки, яка закінчується символом "$"

Вихідні параметри: немає

функція 0Eh - встановити поточним диск DOS

Вхідні параметри:

AH = 0Eh

DL = номер диску (0 - A; 1 - B; 2 - C і т.д.)

Вихідні параметри:

AL = загальна кількість дисководів в системі

функція 19h - зчитати поточний диск DOS

Вхідні параметри:

AH = 19h

Вихідні параметри:

AL = номер поточного диску (0 - A; 1 - B; 2 - C і т.д.)

функція 1Ah - встановити адрес DTA

Вхідні параметри:

AH = 1Ah

DS:DX = адрес для DTA

Вихідні параметри: немає

функція 2Ah - зчитати дату DOS

Вхідні параметри:

AH = 2Ah

Вихідні параметри:

AL = день тижня (0 - неділя, 1 - понеділок, і т.д.)

CX = рік (1980-2099)

DH = місяць (0-12)

DL = число (0-31)

функція 2Bh - встановити дату DOS

Вхідні параметри:

AH = 2Bh

CX = рік (1980-2099)

DH = місяць (0-12)

DL = число (0-31)

Вихідні параметри:

AL = 0 якщо дата встановлена

функція 2Ch - зчитати час DOS

Вхідні параметри:

AH = 2Ch

Вихідні параметри:

CH = години (0-23)

CL = хвилини (0-59)

DH = секунди (0-59)

DL = соті долі секунди (0-99)

функція 2Dh - встановити час DOS

Вхідні параметри:

AH = 2Dh

CH = години (0-23)

CL = хвилини (0-59)

DH = секунди (0-59)

DL = соті долі секунди (0-99)

Вихідні параметри:

AL = 0 якщо час встановлено

функція 36h - зчитати вільну пам'ять диску

Вхідні параметри:

AH = 36h

DL = номер диску (0 - поточний; 1 - A; 2 - B і т.д.)

Вихідні параметри:

AX = 0FFFFh якщо DL містить невірний номер диску, в іншому випадку - кількість секторів на кластер

BX = кількість доступних кластерів

CX = кількість байтів на сектор

DX = кількість кластерів на диску

функція 39h - створити новий каталог

Вхідні параметри:

AH = 39h

DS:DX = адреса ASCIIZ строки з ім'ям каталогу

Вихідні параметри:

AX = код помилки якщо встановлений CF

функція 3Ah - видалити каталог, що існує і є пустим

Вхідні параметри:

AH = 3Ah

DS:DX = адреса ASCIIZ строки з ім'ям каталогу

Вихідні параметри:

AX = код помилки якщо встановлений CF

функція 3Bh - встановити поточний шлях

Вхідні параметри:

AH = 3Bh

DS:DX = адреса ASCIIZ строки з шляхом

Вихідні параметри:

AX = код помилки якщо встановлений CF

функція 3Fh - читати файл через описувач

Вхідні параметри:

AH = 3Fh

BX = описувач файла (0 - читати з клавіатури)

DS:DX = адреса буфера, куди записувати зчитані дані

CX = кількість байтів для читання

Вихідні параметри:

AX = код помилки якщо встановлений CF або кількість реально зчитаних байтів

функція 40h - запис в файл через описувач

Вхідні параметри:

AH = 40h

BX = описувач файла (0 - вивід на дисплей)

DS:DX = адреса буфера, який містить дані для запису

CX = кількість байтів для запису

Вихідні параметри:

AX = код помилки якщо встановлений CF

AL = кількість реально зчитаних байтів

функція 47h - зчитати поточну директорію

Вхідні параметри:

AH = 47h

DS:SI = адреса буфера для шляху

DL = номер диску (0 - поточний; 1 - A; 2 - B і т.д.)

Вихідні параметри:

AX = код помилки якщо встановлений CF

функція 4Сh - завершити програму

Вхідні параметри:

AH = 4Сh

Вихідні параметри: немає

функція 4Eh - знайти перший файл, що відповідає масці

Вхідні параметри:

AH = 4Eh

DS:DX = адреса ASCIIZ строки з ім'ям файлу

CX = атрибут файлу

Вихідні параметри:

AX = код помилки якщо встановлений CF

DTA = заповнена даними якщо не було помилки

функція 4Fh - знайти наступний файл, що відповідає масці

Вхідні параметри:

AH = 4Fh

DS:DX = адреса даних, які були записані функцією 4Eh

Вихідні параметри:

AX = код помилки якщо встановлений CF

DTA = заповнена даними якщо не було помилки

2.2 Процедури, які використовуються в програмі

Процедура GetString - зчитує з клавіатури введені символи до натискання Enter. Якщо кількість введених символів рівна 2 (перевід на наступну стрічку та повернення каретки - при натисканні Enter), то символів введено не було і керування передається на початок програми. В іншому випадку заміняються всі символи "/" на "\".

Процедура AnalyseString - шукає перший символ, який не рівний пробілу. Це для того, щоб оприділити команду, якщо вона була введена після кількох пробілів. Після цього шукаємо довжину команди і записуємо в пам'ять адресу початку команди та її довжину. Тепер переписуємо цю команду в пам'ять так, щоб якщо команда займає менше 4 символів, то праві залишалися нулями. В записаній команді переводимо всі великі літери в малі. Після цього шукаємо адресу початку параметрів та довжину, якщо вони є.

Процедура CurrentPath - щоб оприділити поточний шлях потрібно зчитати поточний диск функцією DOS 19h і, викликавши функцію 47h (7147h - для довгих імен) з вказаним диском в DL, в пам'яті, на яку вказує DS:SI будемо мати шлях без диску.

Процедура CheckDrive - оприділяє готовність диску. Якщо викликати команду DOS 36h з номером диску в DL, і якщо диск не готовий, то AL=0FFFFh, в іншому випадку в регістри запишеться інформація про вільну пам'ять диску.

Процедура WrongCommand - якщо команда, введена користувачем, неправильна, то ця процедура виводить повідомлення про помилку з виведенням неправильної команди.

Процедура PrintDir - якщо 4 біт встановлений в 1, то це означає, що знайдено директорію. Збільшує лічильник директорій і виводить ім'я папки, час і дату останньої зміни папки.

Процедура PrintFile - аналогічно процедурі PrintDir, але викликається лише тоді, коли знайдено файл.

Процедура PrintDate - переводить числа з війкового в ASCII і формує стрічку FileDate. При цьому при цьому подвійне слово, яке міститься в DateFile має таку структуру:

Процедура PrintTime - переводить числа з війкового в ASCII і формує стрічку FileTime. При цьому при цьому подвійне слово, яке міститься в TimeFile має таку структуру:

Процедура GetFreeSpace - за допомогою функції DOS 36h оприділяємо вільне місце на диску. Для цього множимо вміст регістрів AX*BX*DX.

Процедура ConvToBinary - переводить число з ASCII формату в двійковий. Для цього множимо вміст регістру AX на 10, зчитуємо наступну цифру, віднімаємо від неї 30h, додаємо до попереднього значення.

Процедура ConvToASCII - переводить число з війкового в ASCII формат. Для цього число, що знаходиться в AX ділимо на 10 і записуємо остачу в стрічку зліва-направо доти, поки AX не дорівнює нулю.

Процедура ExtendConvToASCII - аналогічна попередній, тільки використовується для переводу великих чисел (до 32-біт).

Процедура proc_cd - якщо команда введена без параметрів, то виводиться поточний шлях. Якщо ж ні, то перевіримо чи введено диск. Якщо так, то треба перевірити чи він доступний. Після цього функцією DOS 3Bh пробуємо встановити вказаних шлях поточним. Якщо CF не встановлений в 1 - то новий шлях встановлено.

Процедура proc_root - подібна до попередньої, але зразу встановлює поточним каталогом кореневий каталог диску.

Процедура proc_updir - змінює каталог на батьківський. Для цього знаходимо з кінця стрічки перший символ "\", замість нього записуємо 0 і функцією DOS 3Bh встановлюємо батьківський каталог поточним.

Процедура proc_md - для створення директорії. Якщо після виклику функції DOS 39h прапорець CF=0, то директорія створена, в іншому випадку AX містить код помилки.

Процедура proc_rd - для видалення директорії. Якщо після виклику функції DOS 3Ah прапорець CF=0, то директорія видалена, в іншому випадку AX містить код помилки.

Процедура proc_dir - виводить список файлів та каталогів. Для цього спочатку потрібно встановити адресу DTA на локальний буфер та задати маску пошуку (*.* - для всіх файлів та папок). Щоб отримати мітку диску, потрібно викликати функцію DOS 4Eh з атрибутом в CX=8h. Тепер шукаємо перший каталог. Задаємо атрибути: 00110111b, де

біт 0 - файл тільки для читання;

біт 1 - прихований файл;

біт 2 - системний файл;

біт 3 - мітка

біт 4 - каталог;

біт 5 - архівний файл.

Тепер шукаємо наступний каталог функцією DOS 4Fh. Повторюємо доти, поки прапорець CF=0. Після цього цими ж самими функціями шукаємо всі файли, лише 4 біт атрибутів встановлюємо в 0.

Процедура proc_drive - використовується для зміни активного диску. Для цього спочатку перевіряємо чи доступний новий диск, а потім функцією DOS 0Eh встановлюємо.

Процедура proc_time - зчитує системний час і виводить його на екран. Після цього програма знаходиться в режимі зчитування символів з клавіатури. Якщо були введені символи, то відбувається спроба встановити новий час, в іншому випадку відбувається передача керування на початок програми.

Процедура proc_date - аналогічна попередній, тільки виводить системну дату і день тижня. Після виклику функції DOS 2Ah в AL знаходиться день тижня, починаючи з неділі. Щоб вивести день тижня за допомогою букв, треба помножити вміст регістру на 2 і додати це число до адреси, за якою міститься стрічка з днями тижня.

2.3 Макроси, які використовуються в програмі

Для зручності і спрощення читання програми я написав 3 макроси:

PrintStr - макрос виводить на екран стрічку за допомогою функції DOS 9h. Вхідним параметром є мітка, за якою в пам'яті розміщена стрічка. Стрічка повинна закінчуватись символом "$".

OutToScreen - макрос для виводу строки на екран. Використовує функцію DOS запису у файл або пристрій 40h. Вхідними параметрами є chars - кількість символів для виводу; text - мітка, за якою в пам'яті розміщена стрічка.

WriteToString - макрос для запису в стрічку символів. Використовується для стирання попередніх даних шляхом запису пробілів для тексту та нулів (30h) для стрічок з цифровими даними. Вхідними параметрами є char - символ, який потрібно записати; repeat кількість байтів для запису; string - мітка, за якою в пам'яті розміщена стрічка.

програма інтерпретатор процесор асемблер

Розділ 3. Тестування програми

Програма розроблялася так, щоб мати інтерфейс аналогічний програмі command.com. При запуску програми вона виводить повідомлення:

Iнтерпретатор функцiй MS-DOS: date, time, dir, cd, md, rd.

Курсовий проект. Стахов Є.В., 2003.

D:\Asm\kursova\new>

Щоб виконати будь-яку з команд потрібно в командній стрічці ввести її ім'я та параметри якщо необхідно. При введенні команди TIME програма виводить системний час і чекає вводу нового часу. Ніякий додаткових параметрів вводити непотрібно.

D:\Asm\kursova\new>time

Поточний час: 17:57:53,85

Введiть новий час:

Якщо час введено неправильно, то виводиться повідомлення про помилку:

D:\Asm\kursova\new>time

Поточний час: 17:57:53,85

Введiть новий час: er:fg:df

Введено недопустиме число

При виклику команди DATE програма виводить системну дату

D:\Asm\kursova\new>date

Поточна дата: Нд 15.06.2003

Введiть нову дату (дд-мм-рр):

При введенні недопустимої дати виводитися повідомлення про помилку:

D:\Asm\kursova\new>date

Поточна дата: Нд 15.06.2003

Введiть нову дату (дд-мм-рр): 45.15.2003

Вказана недопустима дата

Команда DIR може викликатися як без параметрів так і з ними. Якщо викликана без параметрів, то програма виводить вміст поточного каталогу.

D:\Asm\kursova\new>dir

Том в пристрої D має мiтку PROGRAMS

Вмiст папки D:\Asm\kursova\new

. <ПАПКА> 23/06/2003 08:06:20

.. <ПАПКА> 23/06/2003 08:06:20

COMPIL.BAT 46 14/06/2003 22:23:44

...

TD.EXE 491808 10/06/1992 03:10:00

TLINK.EXE 53414 07/05/1990 02:00:00

9 файлiв 829203 байт

2 папок 788350976 байт вiльно

Якщо викликати з параметрами, то програма виведе список файлів та каталогів у вказаній директорії.

D:\Asm\kursova\new>dir c:

Том в пристрої C має мiтку System

Вмiст папки c:

DOCUME~1 <ПАПКА> 07/03/2003 18:36:56

...

PAGEFILE.SYS 150994944 23/06/2003 07:42:14

11 файлiв 151250900 байт

5 папок 49414144 байт вiльно

При виклику команди MD без параметрів виводиться підказка:

D:\Asm\kursova\new>md

Створення директорії

MD [диск:]шлях

D:\Asm\kursova\new>

Якщо директорію створити не вдалося, виводиться відповідне повідомлення з причиною.

D:\Asm\kursova\new>md newfol\new

Вказаний шлях не знайдено

D:\Asm\kursova\new>md newfol

D:\Asm\kursova\new>md newfol\new

D:\Asm\kursova\new>md newfol

Немає доступу до каталогу, або вiн вже iснує

Команда RD працює аналогічно попередній команді

D:\Asm\kursova\new>rd

Видалення директорiї

RD [диск:]шлях

D:\Asm\kursova\new>rd newfol

Немає доступу до каталогу, або вiн не пустий

D:\Asm\kursova\new>rd newfol\new

D:\Asm\kursova\new>rd newfol

D:\Asm\kursova\new>rd d:\asm\kursova\new

Каталог є поточним

При виклику команди CD без параметрів виводиться поточний каталог.

D:\Asm\kursova\new>cd

D:\Asm\kursova\new

Якщо вказати каталог на іншому диску, то команда встановить його, але активним залишить цей диск. Щоб перейти в цю папку потрібно змінити диск.

D:\Asm\kursova\new>cd c:\winnt

D:\Asm\kursova\new>c:

C:\WINNT>

Щоб перейти на 1 директорію вверх потрібно ввести CD.. або CD .., щоб перейти в кореневий каталог потрібно ввести CD\ або CD \

D:\Asm\kursova\new>cd ..

D:\Asm\kursova>cd..

D:\Asm>cd\

D:\>

Якщо ввести неправильну команду, то програма повідомить про це:

D:\Asm\kursova\new>copy

"copy" не є правильною командою

Вихід з програми здійснюється викликом команди EXIT.

ВИСНОВКИ

В результаті проведеної роботи я склав програму-інтерпретатор функцій DOS: TIME, DATE, DIR, CD, MD, RD. Програма написана на мові Асемблера. Всі команди, поставлені в завданні реалізовані та виконуються без помилок. Програма має стандартний інтерфейс, аналогічний як у програмі command.com. Під час тестування програми помилок не виникало.

Програма складена на основі функцій DOS, які дозволяють отримати будь-яку інформацію про диск.

Дана програма може бути основою для написання більш складніших програм, з більшою кількістю команд. Для цього потрібно лише добавити нову процедуру.

СПИСОК ВИКОРИСТАНОЇ ЛІТЕРАТУРИ

1. Абель П. Язык Ассемблера для IBM PC и программирования: Пер. с англ. - М.: Высшая школа, 1992.

2. Юров В., Хорошенко С. Assembler: учебный курс - СПБ: Издательство "Питер", 1999

ДОДАТОК А

Лістинг програми

.model small

stack 100h

.386

PrintStr macro text ; макрос для виводу стрічки на екран

mov ah, 9h

lea dx, text

int 21h

endm

OutToScreen macro chars, text ; макрос для виводу строки на екран

push bx

mov ah, 40h ; функція DOS запису в файл або на пристрій

mov bx, 1h ; стандартний пристрій виводу

mov cx, chars ; кількість символів для виводу

lea dx, text

int 21h

pop bx

endm

WriteToString macro char, repeat, string ; макрос для запису в стрічку

mov al, char ; символу char repeat разів

mov cx, repeat

lea di, string

rep stosb

endm

.data

MaxStringLength = 256

InputStringLength dw ?

InputString db MaxStringLength dup (?)

Command db 4 dup (?)

Path db MaxStringLength dup (?)

StringTab dw 0,0,0,0

ErrorCommand db '" не є правильною командою', 13, 10, 13, 10, "$"

Drive db MaxStringLength dup (?)

DTA db 21 dup (0) ; описуємо структуру DTA

AttrFile db 0 ; атрибут файлу

TimeFile dw 0 ; час створення файлу

DateFile dw 0 ; дата створення файлу

SizeFile dd 0 ; розмір файлу

NameFile db 13 dup (0); ім'я файлу з розширенням

CRLF db 13, 10, "$" ; перевід курсору на наступну стрічку

About db "Iнтерпретатор функцiй MS-DOS: date, time, dir, cd, md, rd.",

13, 10, 'Курсовий проект. Стахов Є., 2003.', 13, 10, 10, "$"

CDError db "Вказаний шлях не знайдено", 13, 10, "$"

MDAbout db "Створення директорiї", 13, 10, 10, " MD [диск:]шлях", 13,

10, 10, "$"

MDError db "Виникла невiдома помилка", 13, 10, 10, "$"

MDError1 db "Вказаний шлях не знайдено", 13, 10, 10, "$"

MDError2 db "Немає доступу до каталогу, або вiн вже iснує", 13, 10, 10,

"$"

RDAbout db "Видалення директорiї", 13, 10, 10, " RD [диск:]шлях", 13,

10, 10, "$"

RDError db "Виникла невiдома помилка", 13, 10, 10, "$"

RDError1 db "Вказаний шлях не знайдено", 13, 10, 10, "$"

RDError2 db "Немає доступу до каталогу, або вiн не пустий", 13, 10, 10,

"$"

RDError3 db "Каталог є поточним", 13, 10, 10, "$"

Date dw 0,0,0,0 ; число/місяць/рік/день тижня

CurDate db "Поточна дата: Пн 00.00.0000", 13, 10, "$"

NewDate db "Введiть нову дату (дд-мм-рр): $"

DateError db "Вказана недопустима дата", 13, 10, "$"

Time dw 0,0,0,0 ; години/хвилини/секунди/соті долі секунди

CurTime db "Поточний час: 00:00:00,00", 13, 10, "$"

NewTime db "Введiть новий час: $"

TimeError db "Вказаний недопустимий час", 13, 10, "$"

Day db "НдПнВтСрЧтПтСб"

ErrorNumber db "Введено недопустиме число", 13, 10, 10, "$"

ErrorDrive db "Системi не вдається знайти вказаний диск", 13, 10, 10,

"$"

dir db "Вивiд списку файлiв та каталогiв", 13, 10, 10, "$"

LabelMess db " Том в пристрої має мiтку $"

NoLabelMess db " Том в пристрої не має мiтки$"

FolderMess db " Вмiст папки $"

DirStr db " <ПАПКА> $"

FileSize db " $"

TotalFileSize dd 0

FreeSize dd 0

Space db " $"

NumFile db 0 ; зберігається кількість файлів в каталозі

NumDir db 0 ; зберігається кількість підкаталогів в каталозі

FileDate db "00/00/0000$"

FileTime db "00:00:00$"

CurrDrive db ?, ":\*.*", 0

TotalFiles db " файлiв "

TotalFileSizeASCII db " "

db " байт", 13, 10

TotalFolders db " папок "

FreeSizeASCII db " "

db " байт вiльно", 13, 10, 10, "$"

.code

start:

mov ax, @data

mov ds, ax

mov es, ax

PrintStr About

begin:

call CurrentPath

PrintStr Drive ; вивід поточного шляху

xor eax, eax

xor ebx, ebx

xor ecx, ecx

xor edx, edx

call GetString ; зчитуємо команду з параметрами

call AnalyseString ; виділяємо окремо команду і параметри

lea si, Command ; оприділяємо введену команду

lodsw

xchg al, ah

shl eax, 16

lodsw

xchg al, ah

cmp eax, "exit"

je exit

cmp eax, "md"

jne command1

call proc_md

command1:

cmp eax, "rd"

jne command2

call proc_rd

command2:

cmp eax, "cd"

jne command3

call proc_cd

command3:

cmp eax, "dir"

jne command4

call proc_dir

command4:

cmp eax, "time"

jne command5

call proc_time

command5:

cmp eax, "date"

jne command6

call proc_date

command6:

cmp eax, "cd\"

jne command7

call proc_root

command7:

cmp eax, "cd.."

jne command8

call proc_updir

command8:

and eax, 0FFh

cmp eax, ":"

jne command9

call proc_drive

command9:

call WrongCommand

exit:

mov ah, 4Ch

int 21h

;--------------------------------------------------:

;-------------------- Процедури ---------------:

;::::::::::::::::::::::::::::::::::::::::::

;: Зчитуємо стрічку з стандартного вводу ::

;::::::::::::::::::::::::::::::::::::::::::

GetString proc

mov ah, 3Fh ;читаємо з файла (фактично - з клавіатури)

mov bx, 0h

mov cx, MaxStringLength

lea dx, InputString

int 21h

sub ax, 2

jz begin ; якщо не введено жодного символу, то перехід на початок

mov InputStringLength, ax ; зберігаємо кількість введених символів

mov cx, ax

lea si, InputString

NextLetter:

mov di, si

lodsb ; перевіряємо кожен символ

cmp al, "/"

jne NotSlash

mov al, "\" ; заміняємо всі символи "\" на "/"

stosb

NotSlash:

loop NextLetter

ret

GetString endp

;:::::::::::::::::::::::::::::::::::::::::::::::::::::

;: Виділяємо з введеної стрічки команду та параметр ::

;:::::::::::::::::::::::::::::::::::::::::::::::::::::

AnalyseString proc

WriteToString 0, 8, StringTab ; обнулюємо 8 байтів починаючи з

StringTab

WriteToString 0, 4, Command ; очищуємо команду

mov cx, InputStringLength

inc cx

lea di, InputString

mov al, 20h ; шукаємо перший символ, не рівний 0

repe scasb

jcxz EndString ; перехід якщо досягнуто кінець стрічки

mov bx, di

repne scasb ; шукаємо перший символ, який дорівнює 0

mov dx, di

push dx

sub dx, bx

mov StringTab, dx ; зберігаємо зміщення, з якого починається команда

pop dx

sub dx, 4

mov StringTab+2, dx ; зберігаємо довжину команди

cmp StringTab, 4

jbe NormalLength ; якщо довжина >4, то команда не правильна

call WrongCommand

NormalLength:

std

push cx

push di

mov cx, StringTab

lea si, InputString

add si, StringTab+2

lea di, Command+3

rep movsb ; записуємо команду з права на ліво

cld

mov cx, 4h

lea si, Command

NextLetterCommand:

mov di, si

lodsb ; перев_ряємо кожен символ

; Переводимо великі літери в малі

cmp al, "A" ; якщо менше A

jb NotChange ; то літера не велика

cmp al, "Z" ; якщо більше Z

ja NotChange ; то літера не велика

add al, 20h

stosb

NotChange:

loop NextLetterCommand

pop di

pop cx

jcxz EndString ; якщо cx=0, то параметрів немає

repe scasb ; шукаємо початок параметрів

jcxz EndString ; якщо досягнуто кінця, то параметрів немає

mov dx, di

sub dx, 3

mov StringTab+4, dx ; зберігаємо зміщення, з якого починаються

параметри

repne scasb ; шукаємо кінець параметрів

sub di, dx

sub di, 3

mov StringTab+6, di ; зберігаємо довжину параметрів

mov cx, di

lea si, InputString

add si, dx

lea di, Path

rep movsb ; переписуємо їх в Path

mov al, 0h ; дописуємо в кінець 0

stosb

EndString:

ret

AnalyseString endp

;:::::::::::::::::::::::::::::::

;: Оприділяє поточний каталог ::

;:::::::::::::::::::::::::::::::

CurrentPath proc

mov ah, 19h ; зчитуємо поточний диск DOS

int 21h

inc al ; номер поточного диску (1 - A; 2 - B; 3 - C і т.д.)

mov dl, al

lea di, Drive

add al, 40h

stosb

mov ax, "\:"

stosw

mov ax, 7147h ; зчитуємо поточну директорію

mov dl, 0h

lea si, Drive+3

int 21h

lea di, Drive

mov cx, MaxStringLength

mov al, 0h

repne scasb ; зрегігаємо її в Drive

dec di

mov ax, "$>" ; завершуємо стрічку символами ">" та "$"

stosw

ret

CurrentPath endp

;:::::::::::::::::::::::::::::::

;: Визначає готовність диску::

;:::::::::::::::::::::::::::::::

CheckDrive proc

mov dl, al

sub dl, 60h ;1 - A:, 2 - B: т.д.

push dx

push ax

push bx

mov ah, 36h ;функція визначення вільного місця на диску

int 21h

cmp ax, 0FFFFh ;AX - число секторів в кластер -1

jne IsDrive ;вихід якщо нема диску або диск не готовий

PrintStr ErrorDrive

pop bx

pop ax

pop dx

jmp begin

IsDrive:

pop bx

pop ax

pop dx

ret

CheckDrive endp

;:::::::::::::::::::::::::::::::::::::

;: Якщо введена неправильна команда ::

;:::::::::::::::::::::::::::::::::::::

WrongCommand proc

mov ah, 2h ; виводимо 1 символ на дисплей

mov dl, '"'

int 21h

mov cx, StringTab

mov ah, 40h ; Функція виводу строки на екран

mov bx, 1h

lea dx, InputString+1

add dx, StringTab+2

sub dx, cx

int 21h

PrintStr ErrorCommand

jmp begin

ret

WrongCommand endp

;:::::::::::::::::::::::::::::::::::::

;: Друкує інформацію про директорію ::

;:::::::::::::::::::::::::::::::::::::

PrintDir proc

and AttrFile, 00010000b ; встановлюємо 4 біт

cmp AttrFile, 10h ; провіряємо атрибут: якщо 10h, то каталог

jne ExitPrintDir

inc NumDir

OutToScreen 13, NameFile ; виводимо ім'я директорії

PrintStr DirStr

call PrintDate ; виводимо дату останньої зміни

call PrintTime ; виводимо час останньої зміни директорії

PrintStr CRLF ; встановлюємо курсор на нову стрічку

ExitPrintDir:

WriteToString 0, 13, NameFile ; очищуємо поле для імені файлу

ret

PrintDir endp

;:::::::::::::::::::::::::::::::

;: Друкує інформацію про файл ::

;:::::::::::::::::::::::::::::::

PrintFile proc

inc NumFile

OutToScreen 13, NameFile ; виводимо ім'я файлу

WriteToString 20h, 12, FileSize ; очищуємо поле для запису розміру

файлу

mov eax, SizeFile

add TotalFileSize, eax

lea di, FileSize+10

call ExtendConvToASCII ; переводимо розмір в ASCII формат

PrintStr FileSize

call PrintDate

call PrintTime

PrintStr CRLF

WriteToString 0, 13, NameFile

ret

PrintFile endp

;::::::::::::::::::::::::::::::::::::::::::

;: Друкує дату зміни файлу чи директорії ::

;::::::::::::::::::::::::::::::::::::::::::

PrintDate proc

WriteToString 30h, 2, FileDate

WriteToString 30h, 2, FileDate+3

WriteToString 30h, 4, FileDate+6

mov ax, DateFile

and ax, 0000000000011111b; залишаємо тільки число

lea di, FileDate+1

call ConvToASCII

mov ax, DateFile

and ax, 0000000111100000b; залишаємо тільки місяць

shr ax, 5

lea di, FileDate+4

call ConvToASCII

mov ax, DateFile; залишаємо тільки рік (з 1980)

shr ax, 9

add ax, 1980

lea di, FileDate+9

call ConvToASCII

PrintStr FileDate

PrintStr Space

ret

PrintDate endp

;:::::::::::::::::::::::::::::::::::::::::

;: Друкує час зміни файлу чи директорії ::

;:::::::::::::::::::::::::::::::::::::::::

PrintTime proc

WriteToString 30h, 2, FileTime

WriteToString 30h, 2, FileTime+3

WriteToString 30h, 2, FileTime+6

mov ax, TimeFile

shr ax, 11 ; будемо працювати з годиною

lea di, FileTime+1

call ConvToASCII

mov ax, TimeFile

and ax, 0000011111100000b; залишаємо тільки хвилини

shr ax, 5

lea di, FileTime+4

call ConvToASCII

mov ax, TimeFile

and ax, 0000000000011111b; залишаємо тільки секунди/2

shl ax, 1

lea di, FileTime+7

call ConvToASCII

PrintStr FileTime

ret

PrintTime endp

;:::::::::::::::::::::::::::::::::::::::::::::::::

;: Підраховує кількість вільних байтів на диску ::

;:::::::::::::::::::::::::::::::::::::::::::::::::

GetFreeSpace proc

lea si, CurrDrive

lodsb ; візьмемо поточний диск

mov dl, al

sub dl, 60h ;1 - A:, 2 - B: _ т.д..

mov ah, 36h ;функція оприділення вільного місця на диску

int 21h

cmp ax, 0FFFFh ;AX - число секторів в кластері -1

jne IsDrive1 ;вихід якщо нема диску або диск не готовий

PrintStr ErrorDrive

jmp begin

IsDrive1:

mul cx ; кількість секторів на кластер * кількість байтів на сектор

mul bx ; домножимо ще на кількість вільних кластерів

mov word ptr FreeSize, ax

mov word ptr FreeSize+2, dx

ret

GetFreeSpace endp

;::::::::::::::::::::::::::::::::::::::::

;: Переводить число з ASCII в двійкове ::

;: Вхід: si - адрес строки ::

;: cx - кількість символів ::

;: Вихід: al - результат ::

;::::::::::::::::::::::::::::::::::::::::

ConvToBinary proc

xor ax, ax

xor dx, dx

mov bx, 10

ConvBinary:

push cx

mul bx

mov cl, [si]

cmp cl, 30h

jb ErrNumber

cmp cl, 39h

ja ErrNumber

xor cl, 30h

add al, cl

pop cx

inc si

loop ConvBinary

ret

ErrNumber:

PrintStr ErrorNumber

jmp begin

ret

ConvToBinary endp

;::::::::::::::::::::::::::::::::::::::::::

;: Переводить число з двійкового в ASCII ::

;: Вхід: di - адрес строки ::

;: ax - число ::

;::::::::::::::::::::::::::::::::::::::::::

ConvToASCII proc

mov cx, 10

xor dx, dx

ConvASCII:

div cx

or dl, 30h

mov [di], dl

xor dx, dx

dec di

cmp ax, 0

jnz ConvASCII

ret

ConvToASCII endp

;::::::::::::::::::::::::::::::::::::::::::

;: Переводить число з двійкового в ASCII ::

;: Вхід: di - адрес строки ::

;: eax - число ::

;::::::::::::::::::::::::::::::::::::::::::

ExtendConvToASCII proc

mov ecx, 10

xor edx, edx

ExtendConvASCII:

div ecx

or dl, 30h

mov [di], dl

xor edx, edx

dec di

cmp eax, 0

jnz ExtendConvASCII

ret

ExtendConvToASCII endp

;::::::::::::::::::::::::::::::::::::::::

;: Змінює поточний каталог на вказаний ::

;::::::::::::::::::::::::::::::::::::::::

proc_cd proc

cmp StringTab+6, 0

jne CheckPath ; якщо були введені параметри

lea di, Drive

mov cx, MaxStringLength

mov al, "$"

repne scasb

sub di, 2

stosb

PrintStr Drive

PrintStr CRLF

PrintStr CRLF

call CurrentPath

jmp begin

CheckPath:

lea si, Path+1

lodsw

cmp ax, 003Ah; " :"

jne GoToPath

lea si, Path

lodsb

call CheckDrive ; перевіряємо чи доступний диск

lea di, Drive

sub al, 20h

stosb

sub al, 40h

mov dl, al

mov ax, 7147h ; зчитуємо поточний шлях

lea si, Drive+3

int 21h

lea di, Drive

mov cx, MaxStringLength

mov al, 0h

repne scasb ; шукаємо кінець

dec di

mov al, "$"

stosb ; дописуємо в кінець "$"

PrintStr Drive

call CurrentPath

PrintStr CRLF

PrintStr CRLF

jmp begin

GoToPath:

lea di, Path

add di, StringTab+6

mov al, 0h

stosb

mov ax, 713Bh ; встановлюємо Path поточною директорією

lea dx, Path

int 21h

cmp al, 2h

jne NoCDErr

PrintStr CDError

NoCDErr:

PrintStr CRLF

call CurrentPath

jmp begin

ret

proc_cd endp

;:::::::::::::::::::::::::::::::::::::::::

;: Змінює поточний каталог на кореневий ::

;:::::::::::::::::::::::::::::::::::::::::

proc_root proc

lea di, Drive+3

mov al, 0h

stosb

mov ax, 713Bh ; встановлюємо поточним кореневий каталог

lea dx, Drive

int 21h

cmp al, 2h

jne NoCDRootErr

PrintStr CDError

NoCDRootErr:

PrintStr CRLF

call CurrentPath

jmp begin

ret

proc_root endp

;::::::::::::::::::::::::::::::::::::::::::::

;: Змінює поточний каталог на батьківський ::

;::::::::::::::::::::::::::::::::::::::::::::

proc_updir proc

lea di, Drive

mov cx, MaxStringLength

mov al, "$"

repne scasb ; шукаємо кінець стрічки

std

mov al, "\"

mov cx, MaxStringLength

repne scasb ; шукаємо з права на ліво перший символ "\"

cld

inc di

mov al, 0h

stosb ; замість нього записуємо 0

mov ax, 713Bh

lea dx, Drive

int 21h

PrintStr CRLF

call CurrentPath

jmp begin

ret

proc_updir endp

;::::::::::::::::::::::::::

;: Створює новий каталог ::

;::::::::::::::::::::::::::

proc_md proc

cmp StringTab+6, 0

jne MDIsPath ; якщо було введено ім'я нової папки

PrintStr MDAbout

jmp begin

MDIsPath:

lea dx, Path ;ds:dx вказують на шлях

mov ax, 7139h

int 21h

jc MDIsError ; якщо виникли помилки

PrintStr CRLF

jmp begin

MDIsError:

cmp ax, 3h ; шлях не знайдено

jne MDErr1

PrintStr MDError1

jmp begin

MDErr1:

cmp ax, 5h ; немає доступу, або каталог вже існує

jne MDErr2

PrintStr MDError2

jmp begin

MDErr2:

PrintStr MDError ; інша помилка

jmp begin

ret

proc_md endp

;:::::::::::::::::::::::::::::

;: Видаляє існуючий каталог ::

;:::::::::::::::::::::::::::::

proc_rd proc

cmp StringTab+6, 0

jne RDIsPath ; якщо було введено ім'я папки для видалення

PrintStr RDAbout

jmp begin

RDIsPath:

lea dx, Path

mov ax, 713Ah

int 21h

jc RDIsError ;oбpoбка помилок

PrintStr CRLF

jmp begin

RDIsError:

cmp ax, 2h ;

jne RDErr1

PrintStr RDError1

jmp begin

RDErr1:

cmp ax, 91h ; немає доступу до каталогу

jne RDErr2

PrintStr RDError2

jmp begin

RDErr2:

cmp ax, 7Bh ; каталог є поточним, або не пустим

jne RDErr3

PrintStr RDError3

jmp begin

RDErr3:

PrintStr RDError ; інша помилка

jmp begin

ret

proc_rd endp

;:::::::::::::::::::::::::::::::::::::::::::

;: Виводить список файлів та підкаталогів ::

;:::::::::::::::::::::::::::::::::::::::::::

proc_dir proc

mov ah, 1Ah

lea dx, DTA ; встановлюємо вказівник на свою область DTA

int 21h

cmp StringTab+6, 0

jne IsParameter ; якщо команда була з параметрами

lea di, Drive

mov cx, MaxStringLength

mov bx, cx

mov al, "$"

repne scasb ; знаходимо кінець стрічки

sub bx, cx

dec bx ; знаходимо її довжину

jmp GetLabel

IsParameter:

mov cx, StringTab+6

mov bx, cx

lea si, Path

lea di, Drive

rep movsb ; переписуємо з Path в Drive

dec si

lodsb

cmp al, "\"

je IsSlash

mov al, "\"

stosb ; дописуємо "\" якщо немає

inc bx

IsSlash:

mov al, "$"

stosb ; дописуємо "$"

GetLabel:

lea si, Drive

lodsb ; зчитуємо букву диску

or al, 00100000b ; перетворюємо її в малу

call CheckDrive

lea di, CurrDrive

stosb

and al, 11011111b ; перетворюємо її в велику

lea di, LabelMess+16

stosb

lea di, NoLabelMess+16

stosb

mov ah, 4Eh ; Шукаємо перший файл

mov cx, 8h ; з атрибутом 08h, тобто мітку тому

lea dx, CurrDrive

int 21h

cmp AttrFile, 8h

jne NoLabel ; якщо немає мітки

PrintStr LabelMess

OutToScreen 13, NameFile

WriteToString 0, 13, NameFile

jmp FileList

NoLabel:

PrintStr NoLabelMess

FileList:

PrintStr CRLF

PrintStr CRLF

lea di, Drive-1

add di, bx

mov al, "$"

stosb

PrintStr FolderMess

PrintStr Drive

PrintStr CRLF

PrintStr CRLF

lea di, Drive-1

add di, bx

mov ax, "*\" ; вводимо маску пошуку *.*

stosw

mov ax, "*."

stosw

mov al, 0

stosb

mov NumDir, 0 ; обнуляємо кілікість директорій

mov NumFile, 0 ; файлів

mov TotalFileSize, 0 ; загальний розмір файлів

mov ah, 4Eh ; знаходимо перший каталог

lea dx, Drive

mov cx, 00110111b ; в CX - атрибут каталогу

int 21h

jc SearchFile ; якщо ні одного каталога немає, шукаємо файли

call PrintDir

FindNextDir:

mov ah, 4Fh ; шукаємо наступний каталог

int 21h

jc SearchFile

call PrintDir ; виводимо найдений каталог

jmp FindNextDir ; переходимо на пошук наступного

SearchFile:

mov ah,4Eh ; шукаємо перший файл

mov cx, 00100111b ; в CX - атрибут файлу - (RO+Hid+Sys+Arc)

lea dx, Drive

int 21h

jc NoFile ; якщо файлів нема, то на вихід

call PrintFile ; виводимо ім'я файлу

FindNextFile:

mov ah,4Fh ; продовжуємо пошук файлів

int 21h

jc NoFile

call PrintFile ; виводимо ім'я файлу

jmp FindNextFile

NoFile:

WriteToString 0, 11, TotalFiles

WriteToString 0, 11, TotalFolders

WriteToString 0, 9, TotalFileSizeASCII

WriteToString 0, 9, FreeSizeASCII

mov al, NumFile

xor ah, ah

lea di, TotalFiles+10

call ConvToASCII

mov al, NumDir

xor ah, ah

lea di, TotalFolders+10

call ConvToASCII

call GetFreeSpace ; обраховуємо вільне місце на диску

mov eax, FreeSize

lea di, FreeSizeASCII+9

call ExtendConvToASCII

mov eax, TotalFileSize

lea di, TotalFileSizeASCII+9

call ExtendConvToASCII

PrintStr TotalFiles ; виводимо загальну кількість файлів та каталогів

jmp begin

ret

proc_dir endp

;:::::::::::::::::::::::::::::

;: Встановлює поточний диск ::

;:::::::::::::::::::::::::::::

proc_drive proc

lea si, Command+2

lodsb ; зчитуємо букву диску, який потрібно зробити активним

call CheckDrive ; перевіряємо чи доступний диск

dec dl

mov ah, 0Eh

int 21h

PrintStr CRLF

jmp begin

ret

proc_drive endp

;:::::::::::::::::::::::::::::::::

;: Зчитує та встановлює час DOS ::

;:::::::::::::::::::::::::::::::::

proc_time proc

mov ah, 2Ch ; зчитуємо час

int 21h

mov byte ptr Time, ch ; години

mov byte ptr Time+2, cl ; хвилини

mov byte ptr Time+4, dh ; секунди

mov byte ptr Time+6, dl ; соті долі секунди

lea di, CurTime+24

mov ax, Time+6

call ConvToASCII

lea di, CurTime+21

mov ax, Time+4

call ConvToASCII

lea di, CurTime+18

mov ax, Time+2

call ConvToASCII

lea di, CurTime+15

mov ax, Time

call ConvToASCII

PrintStr CurTime

InputTime:

PrintStr NewTime

mov ah, 3Fh ;читаемо з файла (фактично - з клавіатури)

mov bx, 0h ;файловий хендл клавіатури

mov cx, MaxStringLength

lea dx, InputString

int 21h

sub ax, 2

jnz IsTime

PrintStr CRLF

jmp begin

IsTime:

mov InputStringLength, ax

cmp ax, 8h

je CheckTime

PrintStr TimeError

jmp InputTime

CheckTime:

lea si, InputString

mov cx, 2h

call ConvToBinary

mov Time, ax

inc si

mov cx, 2h

call ConvToBinary

mov Time+2, ax

inc si

mov cx, 2h

call ConvToBinary

mov Time+4, ax

mov ch, byte ptr Time

mov cl, byte ptr Time+2

mov dh, byte ptr Time+4

mov dl, 0h

mov ah, 2Dh ; встановлюємо новий час

int 21h

cmp al, 0ffh ;пpoвіpяємо пpaвильніcть знaчeння

jne NoTimeErr

PrintStr TimeError

NoTimeErr:

PrintStr CRLF

jmp begin

ret

proc_time endp

;::::::::::::::::::::::::::::::::::

;: Зчитує та встановлює дату DOS ::

;::::::::::::::::::::::::::::::::::

proc_date proc

mov ah, 2Ah ; зчитуємо дату

int 21h

mov byte ptr Date, dl ; число

mov byte ptr Date+2, dh ; місяць

mov Date+4, cx ; рік починаючи з 1980

shl al, 1 ; день тижня

mov byte ptr Date+6, al

lea di, CurDate+26

mov ax, Date+4

call ConvToASCII

lea di, CurDate+21

mov ax, Date+2

call ConvToASCII

lea di, CurDate+18

mov ax, Date

call ConvToASCII

lea si, Day

add si, Date+6

lea di, CurDate+14

movsw

PrintStr CurDate

InputDate:

PrintStr NewDate

mov ah, 3Fh

mov bx, 0h

mov cx, MaxStringLength

lea dx, InputString

int 21h

sub ax, 2

jnz IsDate

PrintStr CRLF

jmp begin

IsDate:

mov InputStringLength, ax

cmp ax, 0Ah

je CheckDate

PrintStr DateError

jmp InputDate

CheckDate:

lea si, InputString

mov cx, 2h

call ConvToBinary

mov Date, ax

inc si

mov cx, 2h

call ConvToBinary

mov Date+2, ax

inc si

mov cx, 4h

call ConvToBinary

mov Date+4, ax

mov dl, byte ptr Date

mov dh, byte ptr Date+2

mov cx, Date+4

mov ah, 2Bh ; встановлюємо нову дату

int 21h

cmp al, 0ffh ;пpoвіpяємо пpaвильніcть знaчeння

jne NoDateErr

PrintStr DateError

NoDateErr:

PrintStr CRLF

jmp begin

ret

proc_date endp

;-----------------------------------------:

end start

ДОДАТОК Б

Блок-схема програми

Размещено на Allbest.ru


Подобные документы

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.