Разработка командного процессора, реализующего команды dir и mkdir на ассемблере

         Министерство образования и науки Республики Беларусь

Белорусский Государственный Университет Информатики и Радиоэлектроники

______________________________________________________________________

                Факультет Компьютерного Проектирования

                        Пояснительная записка

                      к курсовому проекту по теме

                 "Разработка коммандного процессора"

                                                                 Выполнил

                                                        студент гр.410703

                                                           Федосенко Д.В.

                                                      Руководитель работы

                                                            Ширинский В.П.

                             Минск  1996

                               Содержание

Введение

1. Анализ технического задания .................................

2. Разработка алгоритма ........................................

3. Разработка структуры данных .................................

4. Кодирование алгоритма .......................................

5. Тестирование и отладка программы ............................

Заключение .....................................................

Литература .....................................................

Приложение .....................................................

                                Введение

    Появление микропроцессоров в 60-е годы связано с  разработкой  ин-

тегральных схем (ИС).  Интегральные схемы объединяли в себе  различные

электронные компоненты в единый элемент на силиконовом чипе. Разработ-

чики установили этот крошечный чипв устройство,  напоминающее  сороко-

ножку,  и включили его в функциональные системы.  В начале 70-х  годов

микрокомпьютеры на процессоре Intel 8008 возвестили о  первом  поколе-

нии микропроцессоров.

    К 1974 г. появилось второе поколение микропроцессоров общего  наз-

начения Intel 8080. Данный успех побудил другие фирмы  к  производству

процессоров Intel 8080 или аналогичных.

    В 1878 г. фирма Intel выпустила  процессор  третьего  поколения  -

Intel 8086,  который обеспечивал некоторую совместимость с 8080 и  яв-

лялся значительным продвижением вперед в данной области.  Для  поддер-

жки более простых устройств и обеспечения совместимости с  устройства-

ми ввода-вывода того времени Intel разработал разновидность  процессо-

ра 8086 - процессор 8088, который в 1981 г.  ьыл выбран фирмой IBM для

ее персональных компьютеров.

    Более развитыми версиями являются для  процессора  8088  процессор

80186, а для процессора 8086 - процессоры 80186, 80286,  80386,  кото-

рые обеспечили дополнительные возможности и повысили мощность вычисле-

ний.

    Распространение микропроцессоров послужило причиной пересмотра от-

ношения к языку Фсскмблер по двум основным причинам. Во-первых,  прог-

раммы, написанные на языке Ассемблер,  требуют знаительно меньше обье-

ма памяти и времени выполнения.  Во-вторых,  знание языка Ассемблер  и

результирующего машинного кода дыет понимание архитектуры машины,  что

врядли обеспечивается при работе на  языках  высокого  уровня.    Хотя

большинство специалистов в области программного обеспечения ведут раз-

работки на языках высокого уровня, таких, как Паскаль или СИ, что про-

ще при написании программ,  но наиболее мощное и эффективное  програм-

мное обеспечение полностью или частично написано на языке Ассемблер.

                     1. Анализ технического задания

    В данном курсовом проекте необходимо разработать программу на язы-

ке Ассемблер для МП Intel 8086 реализующую функции командного  процес-

сора DIR и MKDIR.  Т.е.  наша программа должна создавать подкаталог  c

указанием диска и маршрута  (функция  MKDIR) и  выводить,    указанный

пользоватем каталог. Вовремя создания подкаталога вносятся изменения в

таблицу размещения файлов (FAT),  с тем чтобы сектора,    используемые

этим подкаталогам были доступны другим файлам.

    Для роботы с дисковой памятью в расширенной версии DOS нам понадо-

бятся операции,  которые включают использование строк в формате ASCIIZ

для начальной установки дисковода, пути доступа и имени файла;  файло-

вого номера для доступу к файлу; специальных кодов возврата.

    Для создания подкаталога методом  дескриптора  файла  используется

функция 39H прерывания 21H. В DS:DX заносится строка ASCIIZ , содержа-

щей идентификацию файла (все параметры необязательные),  строка должна

завершаться 00H, например:

                  PATHNAME  DB  'C:\UTIL\NU.EXE',0

Обратная косая (или прямая косая) используется в качестве разделителя.

Hулевой байт (zero) завершает строку (отсюда название ASCIIZ).

    При успешной операции создания подкаталога, флаг CF устанавливает-

ся в 0.  При неуспешной операции флаг CF устанавливается в 1,  а в ре-

гистр AX помещается код ошибки, зависящий от операции (таблица 1.1), в

нашем случае, если не найден указанный диск или путь,  то в AX возвра-

щается код ошибки 03.  В имени создаваемого подкаталога не могут  быть

использованы следующие символы:

             " : ; / \ | ? * + = [ ] . , < >

                                             Таблица 1.1

            ┌────┬──────────────────────────────────────┐

            │ N  │      Описание ошибки                 │

            ├────┼──────────────────────────────────────┤

            │ 01 │ Ошибка номера функции                │

            │ 02 │ Файл не найден                       │

            │ 03 │ Путь доступа не найден               │

            │ 04 │ Открыто слишком много файлов         │

            │ 05 │ Доступ не разрешен                   │

            │ 06 │ Ошибка файлового номера              │

            │ 07 │ Блок управления памятью разрушен     │

            │ 08 │ Hедостаточно памяти                  │

            │ 09 │ Ошибка адреса блока памяти           │

            │ 10 │ Ошибка оборудования                  │

            │ 11 │ Ошибка формата                       │

            │ 12 │ Ошибка кода доступа                  │

            │ 13 │ Ошибка данных                        │

            │ 15 │ Ошибка дисковода                     │

            │ 16 │ Попытка удалить оглавление           │

            │ 17 │ Hе то устройтво                      │

            │ 18 │ Hет больше файлов                    │

            └────┴──────────────────────────────────────┘

    Для организации работы,  нам понадобится знание  структуры  записи

файла каталогов, которая приведена в таблице 1.2.

                                                 Таблица 1.2

         ┌───┬──────────┬───────┬───────────────────────────┐

         │ N │ Смещение │ Длина │   Значение поля           │

         │   │  (байт)  │ (байт)│                           │

         ├───┼──────────┼───────┼───────────────────────────┤

         │1  │    0     │   8   │ Имя файла                 │

         ├───┼──────────┼───────┼───────────────────────────┤

         │2  │    8     │   3   │ Расширение имени файла    │

         ├───┼──────────┼───────┼───────────────────────────┤

         │3  │    11    │   1   │ Байт атрибутов файлов     │

         ├───┼──────────┼───────┼───────────────────────────┤

         │4  │    12    │   10  │ Зарезервировано для DOS   │

         ├───┼──────────┼───────┼───────────────────────────┤

         │5  │    22    │   2   │ Время                     │

         ├───┼──────────┼───────┼───────────────────────────┤

         │6  │    24    │   2   │ Дата                      │

         ├───┼──────────┼───────┼───────────────────────────┤

         │7  │    26    │   2   │ Стартовый номер кластера  │

         ├───┼──────────┼───────┼───────────────────────────┤

         │8  │    28    │   4   │ Размер файла              │

         └───┴──────────┴───────┴───────────────────────────┘

     Вторая функция курсового проекта (команда DIR),  будет реализова-

на с помощью 21-го прерывания.  Функции 21-го прерывания,  которые  мы

будем использовать, рассмотрены в 4 главе.

                        2. Разработка алгоритма

    Разработаем алгоритм для разрабатываемой программы. Данные в прог-

рамму будем передавать в командной строке.  Далее будем  анализировать

командную строку следующим образом:

    1. Если командная строка пуста, то выводим подсказку;

    2. Если встречается первым ключ /D - то выводим текущий директорий;

    3. Если встречается первым ключ /M -  информируем  пользователя  о

том, что он забыл указать имя поддиректория, для его создания;

    4. После этого записываем все до первого пробела в строку PATH -

это будет маска файлов.

    5. Анализируя далее, смотрим,  если стоит /D - то выводим директо-

рий по маске, если стоит /M - то создаем подкаталог по маске.

    Блок схема алгоритма приведена в приложении.

                     3. Разработка структуры данных

    В курсовом проекте задействовано множество переменных:

┌─────────┬────────────────────────────────────────────────────────────┐

│Hазвание │ Содержание переменной                                      │

├─────────┼────────────────────────────────────────────────────────────┤

│ HelpStr │ Текст подсказки                                            │

│ stringT │ К байт всего на данном диске                               │

│ stringF │ К байт свободно на диске                                   │

│ stringU │ Вывод содержимого каталога                                 │

│ err_m1  │ Ошибка номера функции!                                     │

│ err_m2  │ Файл не найден!                                            │

│ err_m3  │ Путь доступа не найден!                                    │

│ err_m4  │ Открыто слишком много файлов!                              │

│ ok_make │ Подкаталог создан!                                         │

│ no_make │ Подкаталог не создан, т.к. вы не указали его имя!          │

│         │ Для вывода подсказке запустите программу без параметров.   │

│ str_f   │ Вы не указали ключ!                                        │

│ str_k   │ Вы указали неверный ключ!                                  │

│ totalKB │ Ячейка для хранения объема диска                           │

│ freeKB  │ Ячейка для хранения размера свободного места               │

│ temp    │ Рабочая переменная                                         │

│ path    │ Текущий каталог (пока не определен - пустой)               │

│ NewDTA  │ Описываем структуру DTA                                    │

│ AttrF   │ Атрибут файла                                              │

│ TimeF   │ Время создания файла                                       │

│ DateF   │ Дата создания файла                                        │

│ SizeF   │ Размер файла                                               │

│ NameF   │ Имя файла вместе с расширением                             │

└─────────┴────────────────────────────────────────────────────────────┘

    Процедуры, входящие в курсовой проект:

┌─────────────────────────────────────────────────────────────────────────┐

│ Процедура высчитывает и выводит время создания файла/каталога           │

│ WrtTime                                                                 │

├─────────────────────────────────────────────────────────────────────────┤

│ Процедура высчитывает и выводит дату создания файла/каталога            │

│ WrtDate                                                                 │

├─────────────────────────────────────────────────────────────────────────┤

│ Забивает пробелами поле, в которое записывается имя файла (NameF)       │

│ Это необходимо для того, чтобы не было наложений имен файлов при выводе │

│ ClrName                                                                 │

├─────────────────────────────────────────────────────────────────────────┤

│ Выводит имя каталога на экран                                           │

│ WrtDir                                                                  │

├─────────────────────────────────────────────────────────────────────────┤

│ Выводит имя файла на экран                                              │

│ WrtFile                                                                 │

├─────────────────────────────────────────────────────────────────────────┤

│ Выводит метку текущего диска                                            │

│ WLabel                                                                  │

├─────────────────────────────────────────────────────────────────────────┤

│ Производит перевод строки и возврат каретки                             │

│ crlf                                                                    │

├─────────────────────────────────────────────────────────────────────────┤

│ Выводит на экран текущий каталог                                        │

│ curdir                                                                  │

├─────────────────────────────────────────────────────────────────────────┤

│ Получает информацию о диске. Номер диска берет из строки поиска         │

│ После вызова в AX - количество секторов в кластере                      │

│              в BX - число свободных кластеров                           │

│              в CX - число байтов в секторе                              │

│              в DX - число кластеров на диске                            │

│ GetInfo                                                                 │

│                                                                         │

├─────────────────────────────────────────────────────────────────────────┤

│ Выводит размер текущего диска в Килобайтах                              │

│ totsize                                                                 │

├─────────────────────────────────────────────────────────────────────────┤

│ Выводит размер свободного пространства                                  │

│ текущего диска в Килобайтах                                             │

│ fresize                                                                 │

├─────────────────────────────────────────────────────────────────────────┤

│ Процедура вывода числа в десятичном формате                             │

│ Decimal                                                                 │

└─────────────────────────────────────────────────────────────────────────┘

                       4. Кодирование алгоритма

    Запишем разработанный нами алгоритм в мнемокоде на языке Ассемблер.

    Далее более подробно опишем основные прерывания, которые будем ис-

пользовать.

    Основным прерыванием, используемым в программе,  является прерыва-

ния INT 21H (DOS Functions).  Используемые  функции  этого  прерывания

следующие:

 Параметры     Описание

 Входные: AH    02H - Вывод на дисплей

          DL    символ для посылки на стандартное устройство

 Выходные: нет

 ───────────────────────────────────────────────────────────────────────────

 Входные: AH    09H - Вывод строки на дисплей

          DS:DX Адрес строки, заканчивающаяся знаком '$' (ASCII 24H)

 Выходные: нет

 ───────────────────────────────────────────────────────────────────────────

 Входные: AH    1aH - Установка адреса DTA.

          DS:DX адресс DTA области

 Выходные: нет

 ───────────────────────────────────────────────────────────────────────────

 Входные:  AH    19H - Получить информацию о текущем диске

 Выходные: AL    DOS current default drive number (0=A, 1=B, и т.д.)

 ───────────────────────────────────────────────────────────────────────────

 Входные:  AH    36H - Получить информацию о свободном месте на диске

           DL    drive number (0=default, 1=A, и т.д.)

 Выходные: AX    ffffH   если DL было invalid drive number

                 иначе    количество секторов верно

           BX    количество свободных секторов (allocation units)

           CX    байт на сектор (обычно 512)

           DX    общее количество секторов на диске

 Доп.информация: Выходная информация обычно подсчитывается как

          общий размер диска и количество свободного места на диске:

          Если AX = ffffH, то вы не правильно указали диск.

          Иначе,  свободного места в байтах = (AX * CX * BX)

                     общий размер в байтах  = (AX * CX * DX)

          Если сектора по 512 байт, более просто подсчитывать  КБ:

                     свободного места в КБ  = (AX * BX) / 2

                     общий размер в КБ      = (AX * DX) / 2

 ───────────────────────────────────────────────────────────────────────────

 Входные: AH    3fH - Создать подкаталог

          Функция описывалась нами ранее.

 ───────────────────────────────────────────────────────────────────────────

 Входные: AH    47H - Информация о текущем директории

          DL    drive number (0=default, 1=A, etc.)

          DS:SI address of a local buffer to hold a pathname (64 bytes)

 Выходные: AX    передается ошибка (Таблица 1.1)

 ───────────────────────────────────────────────────────────────────────────

 Входные: AH    4fH - Hайти следующий совпадающий файл

          DS:DX адресс данных с предыдущего  4eH поиска файла

 ───────────────────────────────────────────────────────────────────────────

 Входные: AH    4eH - Hвайти первый совпадающий файл

          DS:DX строка пути к файлу  ASCIIZ

          CX    атрибут файлы для поиска

 ───────────────────────────────────────────────────────────────────────────

 Кроме 21h прерывания мы использовали функцию 0eH прерывания INT 10H:

    Данная функция обеспечивает вывод символа на монитор в режиме  те-

летайпа. Для выполнения этой функции в AL помещают выводимый символ, в

BL цвет текста и номер строницы в BH. Hапример, символы: CR (0dH),  LF

(0aH), звуковой сигнал (07H) и т.д.  Данная функция автоматически кур-

сор, переводит символы на следующую строку,  выполняет прокрутку экра-

на и сохраняет текущие атрибуты экрана.

    Также мы использовали прерывание INT 20H для выхода в DOS.  Оно не

имеет параметров.

    Полный текст программы приведен в Приложении.

                  5. Тестирование и отладка программы

D:\ASM>kp.com  <ВВОД>

KP v1.0, Copyright (c) 1997, БГУИР, Федосенко Д.В.

При запуске без параметров выводит подказку

Запуск с параметром должен иметь вид:  kp диск:\каталог\маска [/D] [/M]

Где маска (при использовании /D) - любые символы и имена, включая * и ?

          (при использовании /M) - название подкаталога.

/D - вывод директория по маске   /M - создание подкаталога по маске

Например:kp C:\LANG\BP\*.* /D - вывод всех файлов и каталогов из C:\LANG\BP

         kp C:\*  /D - вывод только каталогов из корневого каталога диска C:

         kp C:\UTIL /M - создание подкаталога UTIL в корневом диска С:

         kp /D   - вывод всех файлов и каталогов по текущему пути

Если ВЫ используете /M, то указывать название подкаталога обязательно!

D:\ASM>kp c:\cd\*.* /D  <ВВОД>

Вывод содержимого каталога c:\cd\*.*

Метка диска DIMKA

.        <КАТАЛОГ>   29/01/97   18:18:44

..       <КАТАЛОГ>   29/01/97   18:18:44

read_me.txt   1834   19/11/96   17:58:40

rcdsim.com   6604   13/09/95   03:00:00

loadcd.exe   0352   13/09/95   03:00:00

rcdpc.sys     4231   13/09/95   03:00:00

run_me.bat     40   06/02/97   13:54:38

   307240К байт всего на данном диске

   6160К байт свободно на диске

D:\ASM>kp c:\cd\util /M  <ВВОД>

c:\cd\util

Подкаталог создан!

D:\ASM>kp c:\cd\*.* /D

Вывод содержимого каталога c:\cd\*.*

Метка диска DIMKA

.        <КАТАЛОГ>   29/01/97   18:18:44

..       <КАТАЛОГ>   29/01/97   18:18:44

UTIL     <КАТАЛОГ>   10/04/97   19:57:48

read_me.txt   1834   19/11/96   17:58:40

rcdsim.com   6604   13/09/95   03:00:00

loadcd.exe   0352   13/09/95   03:00:00

rcdpc.sys     4231   13/09/95   03:00:00

run_me.bat     40   06/02/97   13:54:38

   307240К байт всего на данном диске

   6152К байт свободно на диске

D:\ASM>kp * /D   <ВВОД>

Вывод содержимого каталога *

Метка диска NPACD

.      <КАТАЛОГ>   19/02/97   19:20:34

..     <КАТАЛОГ>   19/02/97   19:20:34

THELP6<КАТАЛОГ>   07/04/97   22:08:48

   483552К байт всего на данном диске

   8928К байт свободно на диске

    В процессе тестирования были замечены проблемы с выводом  информа-

ции при работе в системе WINDOWS95 (v4.0095).  Автор надеется,  что  с

выходом системы WINDOWS98 проблем не будет.

                               Заключение

    В процессе выполнения курсового проекта я более широко изучил фун-

кции прерываний DOS и BIOS. Hаучился применять их на практике,  а так-

же ознакомился со структурой построения программы,   реализующей  фун-

кйии коммандного процессора.  Hаучился пользоваться справочной и  дру-

гой литературой.

                               Литература

 1. Бек Л. Введение в системной программирование

 2. Соловьев Г.H. Операционная система ЭВМ, Высшая школа, 1989г

 3. Краковяк С.  Основы организации  и  функционирования  операционной

системы ЭВМ

 4. Вишняков В.А., Петровский А.А. Системное обеспечение микроЭВМ

 5. Hортон П.  Персональный компьютер фирмы IBM и операционная система

MS-DOS

 6. Финогенов К.Г. Самоучитель по системным функциям MS-DOS

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

ла, 1992г

                              Приложение

;----------------------------------------

;  Курсовой проект по дисциплине

; "Системное программное обеспечение"

;  студента гр.410703 Федосенко Д.В.

;          (c)1997 БГУИР

;----------------------------------------

        .MODEL TINY

        .CODE

        ORG     100h

begin:  jmp     start

HelpStr db      13,10,'KP v1.0, Copyright (c) 1997, БГУИР, Федосенко Д.В.'

        db      13,10,13,10,'При запуске без параметров выводит подказку'

        db      13,10,'Запуск с параметром должен иметь вид:  kp диск:

\каталог\маска [/D] [/M]'

        db      13,10,'Где маска (при использовании /D) - любые символы и

 имена, включая * и ?'

        db      13,10,'          (при использовании /M) - название

 подкаталога.'

        db      13,10,'/D - вывод директория по маске

 /M - создание подкаталога по маске'

        db      13,10,'Например:kp C:\LANG\BP\*.* /D - вывод всех файлов

 и каталогов из C:\LANG\BP'

        db      13,10,'         kp C:\*  /D - вывод только каталогов из

 корневого каталога диска C:'

        db      13,10,'         kp C:\UTIL /M - создание подкаталога UTIL

в корневом каталоге диска С:'

        db      13,10,'         kp /D   - вывод всех файлов и каталогов по

текущему пути'

        db      13,10,'Если ВЫ используете /M, то указывать название

 подкаталога обязательно!',13,10,'$'

stringT db      'К байт всего на данном диске',13,10,'$'

stringF db      'К байт свободно на диске',13,10,'$'

stringU db      13,10,'Вывод содержимого каталога $'

err_m1  db      13,10,'Ошибка номера функции! $'

err_m2  db      13,10,'Файл не найден! $'

err_m3  db      13,10,'Путь доступа не найден! $'

err_m4  db      13,10,'Открыто слишком много файлов! $'

ok_make db      13,10,'Подкаталог создан! $'

no_make db      13,10,'Подкаталог не создан, т.к. вы не указали его имя!'

        db      13,10,'Для вывода подсказке запустите программу без

параметров.',10,13,'$'

str_f   db      13,10,'Вы не указали ключ! $'

str_k   db      13,10,'Вы указали неверный ключ! $'

totalKB dd      0            ; Ячейка для хранения объема диска

freeKB  dd      0            ; Ячейка для хранения размера свободного места

space   db      '   $'       ; Строка разделения

temp    dw      0            ; Рабочая переменная

path    db      65 dup (0)   ; Текущий каталог (пока не определен - пустой)

NewDTA  db      21 dup (0)      ; Описываем структуру DTA

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

TimeF   dw      0               ; Время создания файла

DateF   dw      0               ; Дата создания файла

SizeF   dd      0               ; Размер файла

NameF   db      13 dup (0)      ; Имя файла вместе с расширением

start:

        push    cs              ; Заносим во все регистры сегмент кода

        pop     ds              ;

        push    cs              ;

        pop     es              ;

;Проверяем строку параметров

        mov     cl,ds:[80h]     ; Число символов параметров

        cmp     cl,0            ; Не равно-ли число параметров нулю ?

        je      help            ; Если параметров нет, переходим

        cmp     cl,1            ; Если один параметр, например файл запущен

        je      help            ; по Ctrl-Enter в NC, то тоже выходим

        mov     al,ds:[82h]     ; Проверяем на ввод без маски

        cmp     al,'/'          ; Наклонная черта ?

        jne     not_help        ; Нет - выходим

        mov     al,ds:[83h]     ; Да - смотрим дальше

        cmp     al,'M'          ; Если введено /M

        je      not_m

        cmp     al,'D'          ; Если введно  /D

        je      noparam

        jmp     not_help

help:

        mov     ah,9            ; Вывод подсказки

        lea     dx,HelpStr

        int     21h

        ret                     ; Выход в DOS

not_m:

        mov     ah,9            ; Подкаталог не созданб т.к. вы не

        lea     dx,no_make      ; указали имя

        int     21h

        ret                     ; Выход в DOS

not_help:                       ; Если маска введена

        mov     ch,0

        mov     di,81h          ; Адрес первого символа параметра

        mov     al,' '          ; Сканировать будем до первого пробела

CheckParam:

        repe    scasb           ; Запускаем сканирование строки

        jne     IsParam

IsParam:                        ; Если пробел найден

        mov     si,di           ; Запоминаем адрес

        dec     si              ; Уменьшаем на единицу

        lea     di,path         ; Устанавливаем адрес строки параметров

        inc     cl

MoveParam:

        lodsb                   ; Загружаем один символ строки параметров

        cmp     al,' '          ; Проверяем, не равен ли он пробелу

        je      EndMoveParam    ; Если равен, значит конец строки

        stosb                   ; Иначе пересылаем в строку параметров - path

        loop    MoveParam       ; Цикл до конца строки

EndMoveParam:

        push    ax              ;сохраним на всякий случай

        lodsb                   ;загружаем еще один символ

        cmp     al,'/'          ;если это /

        je      okk

        mov     ah,9            ;иначе вываливаемся с error

        lea     dx,str_F

        int     21h

        int     20h

okk:    lodsb                   ;загружаем еще один символ

        cmp     al,'D'          ;если это /D

        je      Dire            ;то запуск DirE

        cmp     al,'M'          ;если это /M

        je      MakeE           ;то запускаем MakeE

        mov     ah,9            ;иначе вываливаемся с error

        lea     dx,str_K

        int     21h

        int     20h

DirE:   pop     ax

        mov     al,0            ; Добавляем символ NUL к строке параметров

        mov     [di],al

        mov     ah,9            ; Функция вывода строки

        lea     dx,stringU      ; В DX - адрес строки

        int     21h             ; Выводим строку "Текущий каталог"

        mov     ah,40h          ; Выводим маску поиска

        mov     bx,01

        mov     cx,50

        lea     dx,path

        int     21h

        call    crlf            ; Перевод строки, возврат каретки

        jmp     skip_curdir     ; Обходим определение текущего каталога

NoParam:                        ; Если не заданы параметры

        call    curdir          ; Определяем текущий каталог

skip_curdir:

        lea     dx,NewDTA       ; Устанавливаем указатель на свою область DTA

        mov     ah,1Ah

        int     21h

        call    WLabel          ; Выводим метку диска

        mov     ah,4eh          ; Функция находит первый каталог с маской *.*

        mov     cx,10h          ; В CX - атрибут каталога - 10h

        lea     dx,path         ; В DX - путь для поиска (был определен выше)

        int     21h

        jc      NowFiles        ; Если ни одного каталога нет, ищем файлы

        call    WrtDir          ; Выводим имя первого найденного каталога

FindNextDir:

        mov     ah,4fh        ; Функция продолжает поиск, начатый ф-цией 4eh

        int     21h

        jc      NowFiles        ; Если больше каталогов нет, ищем файлы

        call    WrtDir          ; Выводим найденный каталог

        jmp     FindNextDir     ; Переходим на поиск следующего

NowFiles:

        mov     ah,4eh          ; Функция находит первый файл с маской *.*

        mov     cx,27h          ; В CX - атрибут файла - 27h (RO+Hid+Sys+Arc)

        lea     dx,path         ; В DX - путь для поиска файлов

        int     21h

        jc      halt            ; Если файлов нет, то на выход

        call    WrtFile         ; Если файл найден, выводим его имя

FindNextFile:

        mov     ah,4fh          ; Функция продолжает поиск файлов

        int     21h

        jc      halt            ; Если больше файлов нет, то на выход

        call    WrtFile         ; Выводим имя файла на экран

        jmp     FindNextFile    ; Переход на поиск следующего файла

halt:   call    crlf            ; Перевод строки, возврат каретки

        call    totsize         ; Вывод объема диска

        call    fresize         ; Вывод оставшегося места

        ret                     ; Выход в DOS

;------------- создание подкаталога ---------------------------------

MakeE:  pop ax                  ; восстанавливаем ax

        mov     al,0            ; Добавляем символ NUL к строке параметров

        mov     [di],al

        mov     ah,40h          ; Выводим маску поиска

        mov     bx,01

        mov     cx,50

        lea     dx,path

        int     21h

        mov     ah,39h          ; функция создания подкаталога

        lea     dx,path

        int     21h             ; выполнить

        cmp     ax,01h          ; проверка на ошибку #1

        je      p_err1

        cmp     ax,02h          ; проверка на ошибку #2

        je      p_err2

        cmp     ax,03h          ; проверка на ошибку #3

        je      p_err3

        cmp     ax,04h          ; проверка на ошибку #4

        je      p_err4

        mov     ah,9h           ; Ошибки нет!

        lea     dx,ok_make      ; Вывод строки - Подкаталог создан

        int     21h

        int     20h             ; Выход в DOS

;-------- Обработка ошибок --------------------------------

p_err1: mov     ah,9h

        lea     dx,err_m1

        int     21h

        int     20h

p_err2: mov     ah,9h

        lea     dx,err_m2

        int     21h

        int     20h

p_err3: mov     ah,9h

        lea     dx,err_m3

        int     21h

        int     20h

p_err4: mov     ah,9h

        lea     dx,err_m4

        int     21h

        int     20h             ; Выход в DOS

;------------------------------------------------------------------------

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

;:: Процедура высчитывает и выводит время создания файла/каталога :::

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

WrtTime proc    near

        mov     ah,9

        lea     dx,space

        int     21h

        mov     ax,TimeF

        shr     ax,11

        call    DecWrt

        mov     ax,0e3ah

        int     10h

        mov     ax,TimeF

        shl     ax,5

        shr     ax,10

        call    DecWrt

        mov     ax,0e3ah

        int     10h

        mov     ax,TimeF

        shl     ax,11

        shr     ax,10

        call    DecWrt

        ret

WrtTime endp

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

;::: Процедура высчитывает и выводит дату создания файла/каталога :::

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

WrtDate proc    near

        mov     ah,9

        lea     dx,space

        int     21h

        mov     ax,DateF

        shl     ax,11

        shr     ax,11

        call    DecWrt

        mov     ax,0e2fh

        int     10h

        mov     ax,DateF

        shl     ax,7

        shr     ax,12

        call    DecWrt

        mov     ax,0e2fh

        int     10h

        mov     ax,DateF

        shr     ax,9

        add     ax,80

        call    DecWrt

        ret

WrtDate endp

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

; Забивает пробелами поле, в которое записывается имя файла (NameF)       ::

; Это необходимо для того, чтобы не было наложений имен файлов при выводе ::

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

ClrName proc    near

        lea     si,NameF        ; Получаем адрес имени файла

        mov     cx,1

rp:     cmp     cx,13           ; Если CX=13, то имя обработано полностью

        je      vihod           ; поэтому выходим

        mov     al,0            ; Заносим код символа 0 (пустой символ)

        mov     [si],al         ; Записываем пустой символ в строку NameF

        inc     si              ; Увеличиваем адрес строки

        inc     cx              ; Увеличиваем счетчик записаных символов

        jmp     rp              ; Повторяем цикл

vihod:  ret

ClrName endp

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

;::: Выводит имя каталога на экран ::::

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

WrtDir  proc    near

        cmp     AttrF,10h       ; Проверяем атрибут: если 10h, то каталог

        jne     exit1           ; Иначе на выход

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

        mov     bx,01

        mov     cx,12           ; Выводим 13 символов

        lea     dx,NameF        ; В DX - адрес строки вывода

        int     21h

        mov     ah,9

        lea     dx,dirstr

        int     21h

        call    WrtDate

        call    WrtTime

        call    crlf            ; Перевод строки, возврат каретки

exit1:  call    ClrName         ; Чистим поле вывода

        ret

dirstr  db      '<КАТАЛОГ>$'

WrtDir  endp

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

;::: Выводит имя файла на экран ::::::::

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

WrtFile proc    near

        cmp     AttrF,10h     ; Проверяем атрибут: если не файл, то выходим

        je      exit2

        lea     si,NameF      ; Загружанм адрес строки в SI

        mov     cx,1

loop1:

        cmp     cx,13         ; Проверяем, если CX=13, то вывод закончен

        je      exit2         ; выходим

        mov     al,[si]       ; Заносим в AL выводимый символ

        cmp     al,65         ; Сравниваем его с 'A'

        jl      skip1         ; Если меньше, то не переводим в нижний регистр

        cmp     al,90         ; Сравниваем AL с 'Z'

        jg      skip1         ; Если больше, то не переводим в нижний регистр

        add     al,32         ; Переводим символ в нижний регистр

skip1:

        mov     dl,al

        mov     ah,02           ; Функция вывода символа на экран

        int     21h

        inc     si              ; Увеличиваем адрес

        inc     cx              ; Увеличиваем сченчик

        jmp     loop1           ; Переход на следующий символ

exit2:

        call    ClrName         ; Чистим поле вывода

        mov     ax,word ptr SizeF

        mov     dx,word ptr SizeF+2

        call    Decimal

        call    WrtDate

        call    WrtTime

        call    crlf

        ret

WrtFile endp

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

;::: Выводит метку текущего диска ::::::

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

WLabel  proc    near

        call    ClrName         ; Чистим поле вывода

        mov     ah,9            ; Функция вывода строки на экран

        lea     dx,StringL      ; В DX - адрес строки

        int     21h

        lea     si,path4

        mov     ah,19h          ; Получаем текущий диск

        int     21h

        add     al,41h          ; Переводим его в букву

        mov     [si],al         ; Заносим во временную строку

        lea     si,path         ; Путь поиска

        lea     di,path4        ; Временная строка

        mov     al,[si]         ; Берем первый символ пути поиска

        cmp     al,65           ; Буква диска 'A'?

        jl      not_xchg        ; Если меньше, выходим

        cmp     al,122          ; Буква диска 'z'?

        jg      not_xchg        ; Если больше, выходим

        cmp     al,91           ; Если '[' - выход

        je      not_xchg

        cmp     al,92           ; Если '\' - выход

        je      not_xchg

        cmp     al,93           ; Если ']' - выход

        je      not_xchg

        cmp     al,94           ; Если '^' - выход

        je      not_xchg

        cmp     al,95           ; Если '_' - выход

        je      not_xchg

        cmp     al,96           ; Если '`' - выход

        je      not_xchg

        mov     [di],al

not_xchg:

        mov     ah,4eh          ; Ищем файл

        mov     cx,08h          ; с атрибутом 08h, т.е. метку тома

        lea     dx,path4        ; В DX - путь для поиска

        int     21h

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

        mov     bx,01

        mov     cx,13           ; Выводим 13 символов

        lea     dx,NameF        ; В DX - адрес строки

        int     21h

        call    crlf            ; Перевод строки, возврат каретки

        call    crlf            ; Перевод строки, возврат каретки

        call    ClrName         ; Чистим поле вывода

        ret

StringL db      'Метка диска $'

path4   db      'c:\*.*',0     ; Первый символ будет заменен на текущий диск

WLabel  endp

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

;:::: Производит перевод строки и возврат каретки :::::

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

crlf    proc    near

        mov     ax,0e0dh        ; Функция вывода символа

        int     10h             ; Выводим символ 13 на экран

        mov     ax,0e0ah        ; Функция вывода символа

        int     10h             ; Выводим символ 10 на экран

        ret

crlf    endp

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

;::: Выводит на экран текущий каталог :::::

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

curdir  proc    near

        mov     ah,9            ; Функция вывода строки

        lea     dx,stringC      ; В DX - адрес строки

        int     21h             ; Выводим строку "Текущий каталог"

        lea     si,path

        mov     ah,19h          ; Получаем текущий диск

        int     21h

        add     al,41h          ; Переводим его в букву

        mov     [si],al

        inc     si

        mov     al,58           ; Добавляем символ ':'

        mov     [si],al

        inc     si

        mov     al,92           ; Добавляем символ '\'

        mov     [si],al

        mov     ah,47h          ; Функция получения текущего каталога

        mov     dl,00

        lea     si,path+3       ; Добавляем к диску каталог

        int     21h

        lea     si,path         ; Производим посимвольный вывод полного пути

a10loop:

        cmp     byte ptr [si],0

        je      a20exit

        mov     al,[si]

        mov     dl,al

        mov     ah,02

        int     21h

        inc     si

        jmp     a10loop

a20exit:

; Добавляем к текущему пути маску *.* для поиска каталогов и файлов

        dec     si            ; Уменьшаем адрес на 1 и получаем последний

        mov     al,[si]       ; символ, а не NUL

        inc     si            ; Возвращаем назад SI

        cmp     al,92         ; Проверяем, если посл. символ - слэш, то выход

        je      skip_slash

        mov     al,92           ; Иначе добавляем символ '\'

        mov     [si],al

        inc     si

skip_slash:

        mov     al,42           ; Добавляем символ '*'

        mov     [si],al

        inc     si

        mov     al,46           ; Добавляем символ '.'

        mov     [si],al

        inc     si

        mov     al,42           ; Добавляем символ '*'

        mov     [si],al

        inc     si

        mov     al,0            ; Добавляем символ NUL

        mov     [si],al

        call    crlf

        ret

stringC db      13,10,'Текущий каталог $'

curdir  endp

Div1024 proc    near

        mov     cx,10

dd20:   shr     ax,1

        shr     dx,1

        jnc     dd30

        or      ah,10000000b

dd30:   loop    dd20

        ret

Div1024 endp

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

;:: Получает информацию о диске. Номер диска берет из строки поиска :::

;:: После вызова в AX - количество секторов в кластере              :::

;::              в BX - число свободных кластеров                   :::

;::              в CX - число байтов в секторе                      :::

;::              в DX - число кластеров на диске                    :::

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

GetInfo proc    near

        mov     dl,0            ; В DL заносим 0, т.е. текущий диск

        lea     si,path         ; Получаем букву диска из пути поиска

        mov     al,[si]

        sub     al,40h          ; Переводим ее в цифру

        cmp     al,0        ; Номер диска 0 ?

        jl      not_1       ; Если меньше, выходим

        cmp     al,26       ; Номер диска 26 ?

        jg      again       ; Если больше, то идем на проверку строчных букв

        jmp     mov_val     ; Переход на обработку

again:

        sub     al,32       ; Если буква диска строчная, уменьшаем еще раз

        cmp     al,0        ; Номер диска 0 ?

        jl      not_1       ; Если меньше, выходим

        cmp     al,26       ; Номер диска 26 ?

        jg      not_1       ; Если больше, выходим

mov_val:

        mov     dl,al       ; Заносим номер диска

not_1:

        mov     ah,36h      ; Функция получения информации о диске

        int     21h

        ret

GetInfo endp

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

;:: Выводит размер текущего диска в Килобайтах ::::

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

totsize proc    near

        call    GetInfo

        mov     temp,dx         ; Запоминаем число кластеров

        mul     cx              ; Умножаем число секторов на размер сектора

        mul     temp            ; Умножаем все на количество кластеров

        call    Div1024         ; Делим на 1024 и получаем размер в Кбайтах

        mov     word ptr totalKB,ax     ; Запоминаем младшее и старшее слово

        mov     word ptr totalKB+2,dx   ; полученного результата

        call    Decimal

        mov     ah,9

        lea     dx,stringT

        int     21h

        ret

totsize endp

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

;::: Выводит размер свободного пространства ::::

;::: текущего диска в Килобайтах            ::::

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

fresize proc    near

        call    GetInfo

        mul     cx

        mul     bx

        call    Div1024

        mov     word ptr freeKB,ax

        mov     word ptr freeKB+2,dx

        call    Decimal

        mov     ah,9

        lea     dx,stringF

        int     21h

        ret

fresize endp

DecWrt  proc    near

        lea     si,outst        ; очищаем строку

        mov     cl,0

        mov     [si],cl

        mov     [si+1],cl

        lea     si,outst

        mov     cl,48

        mov     [si],cl

        mov     cx,0010

        lea     si,outst+1

a20:    cmp     ax,0010

        jb      a30

        xor     dx,dx

        div     cx

        or      dl,30h

        mov     [si],dl

        dec     si

        jmp     a20

a30:    or      al,30h

        mov     [si],al

        mov     ah,40h          ; выводим строку

        mov     bx,01

        mov     cx,02

        lea     dx,outst

        int     21h

        ret

outst   db      '  '

DecWrt  endp

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

;:: Процедура вывода числа в десятичном формате ::::

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

Decimal proc C uses es di bx cx dx ds

        mov     bx,10

        push    cs

        pop     es

        push    ax              ; Заполняем массив DecString байтами 00

        xor     ax,ax           ;

        cld                     ;

        mov     cx,3            ;

        lea     di,DecStr       ;

        rep     stosw           ;

        pop     ax              ;

        lea     di,DecStr+5     ; DI адресует последний байт массива

        std

        div     bx

        push    ax

        mov     ax,dx

        or      al,30h          ; Преобразуем в ASCII-символ.

        stosb

        pop     ax

c10:

        xor     cx,cx

c20:

        cmp     ax,bx           ; Делимое в AX, делитель в BX.

        jb      c30             ; Частное накапливается в CX.

        sub     ax,bx           ; Деление методом вычитания

        inc     cx              ; (страхует от переполнения)

        jmp     c20

c30:

        or      al,30h          ; Переводим в ASCII

        stosb                   ; Заносим в DecString

        mov     ax,cx

        cmp     ax,bx

        jae     c10

        or      al,0

        jz      c50

        or      al,30h

        stosb

c50:

        mov     ah,9

        lea     dx,space

        int     21h

        mov     ah,9

        lea     dx,DecStr

        int     21h

        ret

DecStr  db      6 dup (0)

        db      '$'

Decimal endp

        end     begin

                                                                                                                                                                                                     



РBР[1]F*.FRM*.MAC
<

Б