Том в пристрої D має мiтку PROGRAMS
Вмiст папки D:\Asm\kursova\new
. <ПАПКА> 23/06/2003 08:06:20
.. <ПАПКА> 23/06/2003 08:06:20.BAT 46 14/06/2003 22:23:44
....EXE 491808 10/06/1992 03:10:00.EXE 53414 07/05/1990 02:00:00
файлiв 829203 байт
папок 788350976 байт вiльно
Якщо викликати з параметрами, то програма виведе список файлів та каталогів у вказаній директорії.:\Asm\kursova\new>dir c:
Том в пристрої C має мiтку System
Вмiст папки c:
DOCUME~1 <ПАПКА> 07/03/2003 18:36:56
....SYS 150994944 23/06/2003 07:42:14
файлiв 151250900 байт
5 папок 49414144 байт вiльно
При виклику команди MD без параметрів виводиться підказка::\Asm\kursova\new>md
Створення директорії[диск:]шлях:\Asm\kursova\new>
Якщо директорію створити не вдалося, виводиться відповідне повідомлення з причиною.:\Asm\kursova\new>md newfol\new
Вказаний шлях не знайдено:\Asm\kursova\new>md newfol:\Asm\kursova\new>md newfol\new:\Asm\kursova\new>md newfol
Немає доступу до каталогу, або вiн вже iснує
Команда RD працює аналогічно попередній команді
D:\Asm\kursova\new>rd
Видалення директорiї[диск:]шлях:\Asm\kursova\new>rd newfol
Немає доступу до каталогу, або вiн не пустий:\Asm\kursova\new>rd newfol\new:\Asm\kursova\new>rd newfol:\Asm\kursova\new>rd d:\asm\kursova\new
Каталог є поточним
При виклику команди CD без параметрів виводиться поточний каталог.:\Asm\kursova\new>cd:\Asm\kursova\new
Якщо вказати каталог на іншому диску, то команда встановить його, але активним залишить цей диск. Щоб перейти в цю папку потрібно змінити диск.:\Asm\kursova\new>cd c:\winnt:\Asm\kursova\new>c::\WINNT>
Щоб перейти на 1 директорію вверх потрібно ввести CD.. або CD .., щоб перейти в кореневий каталог потрібно ввести CD\ або CD \:\Asm\kursova\new>cd ..:\Asm\kursova>cd..:\Asm>cd\:\>
Якщо ввести неправильну команду, то програма повідомить про це::\Asm\kursova\new>copy
"copy" не є правильною командою
Вихід з програми здійснюється викликом команди EXIT.
ВИСНОВКИ
В результаті проведеної роботи я склав програму-інтерпретатор функцій DOS: TIME, DATE, DIR, CD, MD, RD. Програма написана на мові Асемблера. Всі команди, поставлені в завданні реалізовані та виконуються без помилок. Програма має стандартний інтерфейс, аналогічний як у програмі command.com. Під час тестування програми помилок не виникало.
Програма складена на основі функцій DOS, які дозволяють отримати будь-яку інформацію про диск.
Дана програма може бути основою для написання більш складніших програм, з більшою кількістю команд. Для цього потрібно лише добавити нову процедуру.
СПИСОК ВИКОРИСТАНОЇ ЛІТЕРАТУРИ
1. Абель П. Язык Ассемблера для IBM PC и программирования: Пер. с англ. - М.: Высшая школа, 1992.
2. Юров
В., Хорошенко С. Assembler: учебный курс - СПБ: Издательство "Питер",
1999
ДОДАТОК А
Лістинг програми
.model small100h
.386macro text ; макрос для виводу стрічки на екранah, 9hdx, text21h
macro chars, text ; макрос для виводу строки на екранbxah, 40h ; функція DOS запису в файл або на пристрійbx, 1h ; стандартний пристрій виводуcx, chars ; кількість символів для виводуdx, text21hbx
macro char, repeat, string ; макрос
для запису в стрічкуal, char ; символу char repeat разівcx, repeatdi,
stringstosb
.data= 256dw ?db MaxStringLength dup (?)db 4 dup (?)db MaxStringLength dup (?)dw 0,0,0,0db '" не є правильною командою', 13, 10, 13, 10, "$"db MaxStringLength dup (?)db 21 dup (0) ; описуємо структуру DTAdb 0 ; атрибут файлуdw 0 ; час створення файлуdw 0 ; дата створення файлуdd 0 ; розмір файлуdb 13 dup (0); ім'я файлу з розширеннямdb 13, 10, "$" ; перевід курсору на наступну стрічку
db "Iнтерпретатор функцiй MS-DOS: date, time, dir, cd, md, rd.",
, 10, 'Курсовий проект. Стахов Є., 2003.', 13, 10, 10, "$"db "Вказаний шлях не знайдено", 13, 10, "$"
db "Створення директорiї", 13, 10, 10, " MD [диск:]шлях", 13,
"$"
db "Видалення директорiї", 13, 10, 10, " RD [диск:]шлях", 13,
, 10, "$"db "Виникла невiдома помилка", 13, 10, 10, "$"db "Вказаний шлях не знайдено", 13, 10, 10, "$"db "Немає доступу до каталогу, або вiн не пустий", 13, 10, 10,
"$"db "Каталог є поточним", 13, 10, 10, "$"
dw 0,0,0,0 ; число/місяць/рік/день тижняdb "Поточна дата: Пн 00.00.0000", 13, 10, "$"db "Введiть нову дату (дд-мм-рр): $"db "Вказана недопустима дата", 13, 10, "$"
dw 0,0,0,0 ; години/хвилини/секунди/соті долі секундиdb "Поточний час: 00:00:00,00", 13, 10, "$"db "Введiть новий час: $"db "Вказаний недопустимий час", 13, 10, "$"db "НдПнВтСрЧтПтСб"
db "Введено недопустиме число", 13, 10, 10, "$"db "Системi не вдається знайти вказаний диск", 13, 10, 10,
"$"db "Вивiд списку
файлiв та каталогiв", 13, 10, 10, "$"db " Том в пристрої
має мiтку $"db " Том в пристрої не має мiтки$"db " Вмiст
папки $"db " <ПАПКА> $"db " $"dd 0dd 0db "
$"db 0 ; зберігається кількість файлів в каталозіdb 0 ; зберігається
кількість підкаталогів в каталозіdb "00/00/0000$"db
"00:00:00$"db ?, ":\*.*", 0db " файлiв "db "
"" байт", 13, 10db " папок "db " ""
байт вiльно", 13, 10, 10, "$"
.code:ax, @datads, axes, ax
About:CurrentPathDrive ; вивід поточного шляху
eax, eaxebx, ebxecx, ecxedx, edx
GetString ; зчитуємо команду з
параметрамиAnalyseString ; виділяємо окремо команду і параметри
lea si, Command ; оприділяємо введену командуal, aheax, 16al, aheax, "exit"exiteax, "md"command1proc_md:eax, "rd"command2proc_rd:eax, "cd"command3proc_cd:eax, "dir"command4proc_dir:eax, "time"command5proc_time:eax, "date"command6proc_date:eax, "cd\"command7proc_root:eax, "cd.."command8proc_updir:eax, 0FFheax, ":"command9proc_drive:WrongCommand:ah, 4Ch21h
;--------------------------------------------------:
;-------------------- Процедури ---------------:
;::::::::::::::::::::::::::::::::::::::::::
;: Зчитуємо стрічку з стандартного вводу ::
;::::::::::::::::::::::::::::::::::::::::::procah,
3Fh ;читаємо з файла (фактично - з клавіатури)bx, 0hcx, MaxStringLengthdx,
InputString21hax, 2begin ; якщо не введено жодного символу, то перехід на
початокInputStringLength, ax ; зберігаємо кількість введених символівcx, axsi,
InputString:di, si; перевіряємо кожен символal, "/"NotSlashal,
"\" ; заміняємо всі символи "\" на
"/":NextLetterendp
;:::::::::::::::::::::::::::::::::::::::::::::::::::::
;: Виділяємо з введеної стрічки команду та параметр ::
;:::::::::::::::::::::::::::::::::::::::::::::::::::::proc0, 8, StringTab ; обнулюємо 8 байтів починаючи з 0, 4, Command ; очищуємо командуcx, InputStringLengthcxdi, InputStringal, 20h ; шукаємо перший символ, не рівний 0scasbEndString ; перехід якщо досягнуто кінець стрічкиbx, discasb ; шукаємо перший символ, який дорівнює 0dx, didxdx, bxStringTab, dx ; зберігаємо зміщення, з якого починається командаdxdx, 4StringTab+2, dx ; зберігаємо довжину командиStringTab, 4NormalLength ; якщо довжина >4, то команда не правильнаWrongCommand:cxdicx, StringTabsi, InputStringsi, StringTab+2di, Command+3movsb ; записуємо команду з права на лівоcx, 4hsi, Command:di, si; перев_ряємо кожен символ
; Переводимо великі літери в маліal, "A" ; якщо менше ANotChange ; то літера не великаal, "Z" ; якщо більше ZNotChange ; то літера не великаal, 20h:NextLetterCommanddicxEndString ; якщо cx=0, то параметрів немаєscasb ; шукаємо початок параметрівEndString ; якщо досягнуто кінця, то параметрів немаєdx, didx, 3StringTab+4, dx ; зберігаємо зміщення, з якого починаються
параметриscasb ; шукаємо кінець
параметрівdi, dxdi, 3StringTab+6, di ; зберігаємо довжину параметрівcx, disi,
InputStringsi, dxdi, Pathmovsb ; переписуємо їх в Pathal, 0h ; дописуємо в
кінець 0:endp
;:::::::::::::::::::::::::::::::
;: Оприділяє поточний каталог ::
;:::::::::::::::::::::::::::::::procah, 19h ; зчитуємо поточний диск DOS21hal ; номер поточного диску (1 - A; 2 - B; 3 - C і т.д.)dl, aldi, Driveal, 40hax, "\:"
ax, 7147h ; зчитуємо поточну директоріюdl, 0hsi, Drive+321hdi, Drivecx, MaxStringLengthal, 0hscasb ; зрегігаємо її в Drivediax, "$>" ; завершуємо стрічку символами ">" та "$"endp
;:::::::::::::::::::::::::::::::
;: Визначає готовність диску::
;:::::::::::::::::::::::::::::::procdl,
aldl, 60h ;1 - A:, 2 - B: т.д.dxaxbxah, 36h ;функція визначення вільного місця
на диску21hax, 0FFFFh ;AX - число секторів в кластер -1IsDrive ;вихід якщо нема
диску або диск не готовийErrorDrivebxaxdxbegin:bxaxdxendp
;:::::::::::::::::::::::::::::::::::::
;: Якщо введена неправильна команда ::
;:::::::::::::::::::::::::::::::::::::procah,
2h ; виводимо 1 символ на дисплейdl, '"'21h
mov cx, StringTabah, 40h ; Функція
виводу строки на екранbx, 1hdx, InputString+1dx, StringTab+2dx,
cx21hErrorCommandbeginendp
;:::::::::::::::::::::::::::::::::::::
;: Друкує інформацію про директорію ::
;:::::::::::::::::::::::::::::::::::::procAttrFile, 00010000b ; встановлюємо 4 бітAttrFile, 10h ; провіряємо атрибут: якщо 10h, то каталогExitPrintDir
NumDir13, NameFile ; виводимо ім'я директоріїDirStrPrintDate ; виводимо дату останньої зміниPrintTime ; виводимо час останньої зміни директоріїCRLF ; встановлюємо курсор на нову стрічку:0, 13, NameFile ; очищуємо поле для імені файлуendp
;:::::::::::::::::::::::::::::::
;: Друкує інформацію про файл ::
;:::::::::::::::::::::::::::::::procNumFile13, NameFile ; виводимо ім'я файлу
20h, 12, FileSize ; очищуємо поле для запису розміру
файлуeax, SizeFileTotalFileSize, eaxdi, FileSize+10ExtendConvToASCII ; переводимо розмір в ASCII форматFileSize
PrintDatePrintTimeCRLF0, 13,
NameFileendp
;::::::::::::::::::::::::::::::::::::::::::
;: Друкує дату зміни файлу чи директорії ::
;::::::::::::::::::::::::::::::::::::::::::proc30h, 2, FileDate30h, 2, FileDate+330h, 4, FileDate+6ax, DateFileax, 0000000000011111b; залишаємо тільки числоdi, FileDate+1ConvToASCII
ax, DateFileax, 0000000111100000b; залишаємо тільки місяцьax, 5di, FileDate+4ConvToASCII
ax, DateFile; залишаємо тільки рік (з 1980)ax, 9ax, 1980di, FileDate+9ConvToASCII
FileDateSpaceendp
;:::::::::::::::::::::::::::::::::::::::::
;: Друкує час зміни файлу чи директорії ::
;:::::::::::::::::::::::::::::::::::::::::proc30h, 2, FileTime30h, 2, FileTime+330h, 2, FileTime+6ax, TimeFileax, 11 ; будемо працювати з годиноюdi, FileTime+1ConvToASCII
ax, TimeFileax, 0000011111100000b; залишаємо тільки хвилиниax, 5di, FileTime+4ConvToASCII
ax, TimeFileax, 0000000000011111b; залишаємо тільки секунди/2ax, 1di, FileTime+7ConvToASCII
FileTimeendp
;:::::::::::::::::::::::::::::::::::::::::::::::::
;: Підраховує кількість вільних байтів на диску ::
;:::::::::::::::::::::::::::::::::::::::::::::::::procsi, CurrDrive; візьмемо поточний дискdl, aldl, 60h ;1 - A:, 2 - B: _ т.д..ah, 36h ;функція оприділення вільного місця на диску21hax, 0FFFFh ;AX - число секторів в кластері -1IsDrive1 ;вихід якщо нема диску або диск не готовийErrorDrivebegin:cx ; кількість секторів на кластер * кількість байтів на секторbx ; домножимо ще на кількість вільних кластерів
word ptr FreeSize, axword ptr
FreeSize+2, dxendp
;::::::::::::::::::::::::::::::::::::::::
;: Переводить число з ASCII в двійкове ::
;: Вхід: si - адрес строки ::
;: cx - кількість символів ::
;: Вихід: al - результат ::
;::::::::::::::::::::::::::::::::::::::::procax,
axdx, dxbx, 10:cxbxcl, [si]cl, 30hErrNumbercl, 39hErrNumbercl, 30hal,
clcxsiConvBinary:ErrorNumberbeginendp
;::::::::::::::::::::::::::::::::::::::::::
;: Переводить число з двійкового в ASCII ::
;: Вхід: di - адрес строки ::
;: ax - число ::
;::::::::::::::::::::::::::::::::::::::::::
;: Переводить число з двійкового в ASCII ::
;: Вхід: di - адрес строки ::
;: eax - число ::
;::::::::::::::::::::::::::::::::::::::::::procecx,
10edx, edx:ecxdl, 30h[di], dledx, edxdieax, 0ExtendConvASCIIendp
;::::::::::::::::::::::::::::::::::::::::
;: Змінює поточний каталог на вказаний ::
;::::::::::::::::::::::::::::::::::::::::_cd
procStringTab+6, 0CheckPath ; якщо були введені параметриdi, Drivecx,
MaxStringLengthal, "$"scasbdi, 2DriveCRLFCRLFCurrentPathbegin:si,
Path+1ax, 003Ah; " :"GoToPathsi, PathCheckDrive ; перевіряємо чи
доступний дискdi, Driveal, 20hal, 40hdl, alax, 7147h ; зчитуємо поточний
шляхsi, Drive+321hdi, Drivecx, MaxStringLengthal, 0hscasb ; шукаємо кінецьdial,
"$"; дописуємо в кінець
"$"DriveCurrentPathCRLFCRLFbegin:di, Pathdi, StringTab+6al, 0hax,
713Bh ; встановлюємо Path поточною директорієюdx, Path21hal,
2hNoCDErrCDError:CRLFCurrentPathbegin_cd endp
;:::::::::::::::::::::::::::::::::::::::::
;: Змінює поточний каталог на кореневий ::
;:::::::::::::::::::::::::::::::::::::::::_root
procdi, Drive+3al, 0hax, 713Bh ; встановлюємо поточним кореневий каталогdx,
Drive21hal, 2hNoCDRootErrCDError:CRLFCurrentPathbegin_root endp
;::::::::::::::::::::::::::::::::::::::::::::
;: Змінює поточний каталог на батьківський ::
;::::::::::::::::::::::::::::::::::::::::::::_updir
procdi, Drivecx, MaxStringLengthal, "$"scasb ; шукаємо кінець
стрічкиal, "\"cx, MaxStringLengthscasb ; шукаємо з права на ліво
перший символ "\"dial, 0h; замість нього записуємо 0ax, 713Bhdx,
Drive21hCRLFCurrentPathbegin_updir endp
;::::::::::::::::::::::::::
;: Створює новий каталог ::
;::::::::::::::::::::::::::_md
procStringTab+6, 0MDIsPath ; якщо було введено ім'я нової папкиMDAboutbegin:dx,
Path ;ds:dx вказують на шляхax, 7139h21hMDIsError ; якщо виникли
помилкиCRLFbegin:ax, 3h ; шлях не знайденоMDErr1MDError1begin:ax, 5h ; немає
доступу, або каталог вже існуєMDErr2MDError2begin:MDError ; інша
помилкаbegin_md endp
;:::::::::::::::::::::::::::::
;: Видаляє існуючий каталог ::
;:::::::::::::::::::::::::::::_rd
procStringTab+6, 0RDIsPath ; якщо було введено ім'я папки для
видаленняRDAboutbegin:dx, Pathax, 713Ah21hRDIsError ;oбpoбка
помилокCRLFbegin:ax, 2h ;RDErr1RDError1begin:ax, 91h ; немає доступу до
каталогуRDErr2RDError2begin:ax, 7Bh ; каталог є поточним, або не
пустимRDErr3RDError3begin:RDError ; інша помилкаbegin_rd endp
;:::::::::::::::::::::::::::::::::::::::::::
;: Виводить список файлів та підкаталогів ::
;:::::::::::::::::::::::::::::::::::::::::::_dir procah, 1Ahdx, DTA ; встановлюємо вказівник на свою область DTA21h
StringTab+6, 0IsParameter ; якщо команда була з параметрамиdi, Drivecx, MaxStringLengthbx, cxal, "$"scasb ; знаходимо кінець стрічкиbx, cxbx ; знаходимо її довжинуGetLabel:cx, StringTab+6bx, cxsi, Pathdi, Drivemovsb ; переписуємо з Path в Drivesial, "\"IsSlashal, "\"; дописуємо "\" якщо немаєbx:al, "$"; дописуємо "$":si, Drive; зчитуємо букву дискуal, 00100000b ; перетворюємо її в малуCheckDrivedi, CurrDriveal, 11011111b ; перетворюємо її в великуdi, LabelMess+16di, NoLabelMess+16ah, 4Eh ; Шукаємо перший файлcx, 8h ; з атрибутом 08h, тобто мітку томуdx, CurrDrive21hAttrFile, 8hNoLabel ; якщо немає міткиLabelMess13, NameFile0, 13, NameFileFileList:NoLabelMess:CRLFCRLF
di, Drive-1di, bxal, "$"
FolderMessDriveCRLFCRLF
di, Drive-1di, bxax, "*\" ; вводимо маску пошуку *.*ax, "*."al, 0
NumDir, 0 ; обнуляємо кілікість директорійNumFile, 0 ; файлівTotalFileSize, 0 ; загальний розмір файлів
ah, 4Eh ; знаходимо перший каталогdx, Drivecx, 00110111b ; в CX - атрибут каталогу21hSearchFile ; якщо ні одного каталога немає, шукаємо файлиPrintDir:ah, 4Fh ; шукаємо наступний каталог21hSearchFilePrintDir ; виводимо найдений каталогFindNextDir ; переходимо на пошук наступного
:ah,4Eh ; шукаємо перший файлcx, 00100111b ; в CX - атрибут файлу - (RO+Hid+Sys+Arc)dx, Drive21hNoFile ; якщо файлів нема, то на вихідPrintFile ; виводимо ім'я файлу:ah,4Fh ; продовжуємо пошук файлів21hNoFilePrintFile ; виводимо ім'я файлуFindNextFile
:0, 11, TotalFiles0, 11, TotalFolders0, 9, TotalFileSizeASCII0, 9, FreeSizeASCIIal, NumFileah, ahdi, TotalFiles+10ConvToASCIIal, NumDirah, ahdi, TotalFolders+10ConvToASCII
GetFreeSpace ; обраховуємо вільне місце на дискуeax, FreeSizedi, FreeSizeASCII+9ExtendConvToASCII
eax, TotalFileSizedi,
TotalFileSizeASCII+9ExtendConvToASCIITotalFiles ; виводимо загальну кількість
файлів та каталогівbegin_dir endp
;:::::::::::::::::::::::::::::
;: Встановлює поточний диск ::
;:::::::::::::::::::::::::::::_drive
procsi, Command+2; зчитуємо букву диску, який потрібно зробити
активнимCheckDrive ; перевіряємо чи доступний дискdlah, 0Eh21hCRLFbegin_drive
endp
;:::::::::::::::::::::::::::::::::
;: Зчитує та встановлює час DOS ::
;:::::::::::::::::::::::::::::::::_time procah, 2Ch ; зчитуємо час21hbyte ptr Time, ch ; годиниbyte ptr Time+2, cl ; хвилиниbyte ptr Time+4, dh ; секундиbyte ptr Time+6, dl ; соті долі секундиdi, CurTime+24ax, Time+6ConvToASCIIdi, CurTime+21ax, Time+4ConvToASCIIdi, CurTime+18ax, Time+2ConvToASCIIdi, CurTime+15ax, TimeConvToASCII
CurTime:NewTime
ah, 3Fh ;читаемо з файла (фактично - з клавіатури)bx, 0h ;файловий хендл клавіатуриcx, MaxStringLengthdx, InputString21hax, 2IsTimeCRLFbegin:InputStringLength, axax, 8hCheckTimeTimeErrorInputTime:si, InputStringcx, 2hConvToBinaryTime, axsicx, 2hConvToBinaryTime+2, axsicx, 2hConvToBinaryTime+4, ax
ch, byte ptr Timecl, byte ptr
Time+2dh, byte ptr Time+4dl, 0hah, 2Dh ; встановлюємо новий час21hal, 0ffh
;пpoвіpяємо пpaвильніcть знaчeнняNoTimeErrTimeError:CRLFbegin_time endp
;::::::::::::::::::::::::::::::::::
;: Зчитує та встановлює дату DOS ::
;::::::::::::::::::::::::::::::::::_date procah, 2Ah ; зчитуємо дату21hbyte ptr Date, dl ; числоbyte ptr Date+2, dh ; місяцьDate+4, cx ; рік починаючи з 1980al, 1 ; день тижняbyte ptr Date+6, aldi, CurDate+26ax, Date+4ConvToASCIIdi, CurDate+21ax, Date+2ConvToASCIIdi, CurDate+18ax, DateConvToASCIIsi, Daysi, Date+6di, CurDate+14
CurDate:NewDate
ah, 3Fhbx, 0hcx, MaxStringLengthdx, InputString21hax, 2IsDateCRLFbegin:InputStringLength, axax, 0AhCheckDateDateErrorInputDate:si, InputStringcx, 2hConvToBinaryDate, axsicx, 2hConvToBinaryDate+2, axsicx, 4hConvToBinaryDate+4, ax
dl, byte ptr Datedh, byte ptr Date+2cx, Date+4ah, 2Bh ; встановлюємо нову дату21hal, 0ffh ;пpoвіpяємо пpaвильніcть знaчeнняNoDateErrDateError:CRLFbegin_date endp
;-----------------------------------------:start
ДОДАТОК Б
Блок-схема програми