бесплатные рефераты

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

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

4

зміст

вступ 3

1. Постановка задачі 4

2. Програмний інструментарій 5

2.1. Вибір засобу виконання поставленої задачі. 5

2.2. Функції переривання INT 21h MS DOS, що використані при роботі програм 5

2.2.1. Функції роботи із DTA 5

2.2.2. Інші функції переривання INT 21h, що необхідні для використання у програмі, що розробляється 7

3. Розробка задачі на мові асемблер 10

3.1. Допоміжні процедури 10

3.1.1. Модуль PARAMS.asm 10

3.1.2. Модуль STRIO.asm 14

3.1.3. Модуль BINASC.asm 17

3.2. Розробка основної програми DR.asm 20

4. Розробка задачі на мові високого рівня із використанням асемблерних фрагментів коду 30

4.1. Розробка програми на Pascal 30

Висновки 34

Список використаних джерел 35

Додатки 36

вступ

Еволюція мов програмування нараховує вже не один десяток років. Пройдено великий етап від мов структурного програмування (таких як С) до систем багатомовного програмування, на роль яких претендують такі бренди як С#, Java, та ін. Однак слід зазначити, що незважаючи на постійне оновлення мов високого рівня щодо їх пристосування до зростаючих потреб програмістів, головна їх задача лишається тією ж самою - транслювати свої команди у машинний код. Тобто, не має ніякої різниці, якою мовою виконувати задачу - результат лишається той же; відмінність полягає лише у тому, як ця мова інтерпретує рішення програміста у мову машинних кодів. Тому відповідь на питання - чому мова асемблера, залишаючись практично незмінною у своїй ідеології і лексичній базі (цього не можна сказати, наприклад, про сімейство С), лишається й досі конкурентноспроможною іншим мовам - є цілком зрозумілою: вона, як мова програмування низького рівня, найближча до мови комп'ютера і, наразі, найбільш ефективна.

Мета даного курсового проекту - відбити ідеологію мови асемблера і продемонструвати можливості, які надає їй взаємодія із середовищем MS DOS, на прикладі розробки програми перегляду каталогів і виводу інформації про файли, що в них містяться.

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

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

Таким чином, даний курсовий проект має продемонструвати переваги і недоліки програмування мовами низького і високого рівня, а також розкрити деякі аспекти роботи середовища MS DOS і його функцій.

6

1. Постановка задачі

Згідно із темою даного курсового проекту його задача - показати яким чином можна в середовищі MS DOS реалізувати вивід на екран всіх даних по файлам і директоріям, що містяться в заданій директорії, а також розробити програму, що реалізує ці дії. Оскільки робота відбувається у середовищі MS DOS, цілком очевидно, що можна використовувати всі інструменти і можливості, що надає це середовище програмісту.

Програма має бути виконана мовою асемблера, а також можливий варіант створення програми на мові високого рівня (наприклад Pascal, C та ін.) із використанням фрагментів асемблерного коду, що виконують основний алгоритм задачі.

Програми мають містити коментарі і схеми алгоритмів.

2. Програмний інструментарій

2.1. Вибір засобу виконання поставленої задачі

Існує два шляхи вирішення поставленої задачі. Розглянемо кожний з них окремо.

Перший засіб

Послідовне переміщення по дереву каталогу шляхом безпосереднього читання (за допомогою другої функції переривання INT 13h BIOS) секторів пам'яті, починаючи із ROOT, і пошуку необхідного підкаталогу згідно із вказаним шляхом до потрапляння у кінцевий каталог із виводом даних о всіх файлах і директоріях, що в ньому містяться [1, 2].

Однак даний метод надзвичайно складний, має прив'язку до певної системи FAT, організації BOOT і таблиці розділів, потребує прямого звертання до жорсткого диску, що не свідчить в його користь.

Другий засіб

Пов'язаний із специфікою роботи MS DOS. Коли програма починає виконуватись, регістри DS:0000 і ES:0000 вказують на початок PSP (Program Segment Prefix - префікс програмного сегмента) - об'єм пам'яті, в якому міститься інформація о розмірі доступної пам'яті, опції із рядка команд, імена файлів, оточення, а також DTA (розмір 43 байти) [4, 6].

DTA має наступну структуру:

- Резервна область.

- Атрибут.

- Час створення файлу.

- Розмір файлу.

- Ім'я із розширенням файлу.

Таким чином DTA дає повну і вичерпну інформацію о файлі. Тобто, читаючи послідовно DTA кожного файлу директорії, можна отримати інформацію по кожному файлу і вивести її на екран.

Пошук DTA файлів реалізується за допомогою спеціальних функцій переривання INT 21h MS DOS. Для виводу інформації на екран, і завершення програми, теж використовуються спеціальні функції переривання INT 21h.

2.2. Функції переривання INT 21h MS DOS, що використані при роботі програм

2.2.1. Функції роботи із DTA

Середовище MS DOS пропонує набір функцій переривання INT 21h, що дозволяють працювати із DTA - встановити його адресу (1Ah), дати поточний DTA (2Fh), заповнити DTA при знаходженні першого файлу (4Eh), заповнити DTA при знаходженні наступного файлу (4Fh). Розглянемо кожну з цих функцій окремо:

1Ah функція INT 21h [6]

Вхід: AH 1Ah

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

Вихід: не має

Дана функція встановлює адресу для DTA. В регістрову пару DS:DX заноситься, відповідно, сегмент і зміщення буфера розміром >43 байтів, в який буде зберігатись DTA. Якщо адреса DTA змінюється вашою програмою, бажано зберегти попередню адресу DTA (за допомогою функції 2Fh INT 21h) і відновити її після завершення програми.

Приклад:

mov ah, 1Ah ; в ah номер функції

mov dx, offset buffer ; в dx поміщується зміщення буфера,

; сегмент лишається незмінний

int 21h

В даному прикладі перевизначається адреса для буфера DTA.

2Fh функція INT 21h [6]

Вхід: AH 2Fh

Вихід: ES:BS адреса початку поточної DTA.

Функція повертає адресу початку області вводу/виводу DTA. В AH заноситься номер функції; в регістровій парі ES:BS повертається адреса початку DTA.

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

Приклад:

push es ; збереження у стеку регістрів es, bx, що зміняться

push bx

mov ah, 2Fh ;в ах номер функції

int 21h

mov [DTAs], es ; збереження адреси DTA

mov [DTAo], bx

pop bx ; відновлення попередніх значень регістрів bx і es

pop es ; із стеку

В даному прикладі у змінних DTAs і DTAo зберігається адреса DTA, регістри bx, es незмінні.

4Eh функція INT 21h [6]

Вхід: AH 4Fh

DS:DX адреса ASCII рядка із маскою імені файлу

СХ атрибут файлу для порівняння

Вихід: АХ код помилки, якщо в CF=1 буфер DTA заповнений даними.

Дана функція знаходить ім'я першого файлу у переліку, що відповідає заданій масці і атрибуту, і поміщує інформацію про нього в буфер DTA. В AH поміщується номер функції; регістрова пара вказує на рядок, що задає маску імені файлу; в СХ міститься атрибут файлу.

В імені файлу і розширенні допускаються узагальнені символи "*" і "?".

Функція повертає код помилки в AX, якщо файл не знайдений, або заповнює буфер DTA даними про файл.

4Fh функція INT 21h [6]

Вхід: AH 4Fh

DS:DX адреса даних, повернутих попередньою 4Eh

функцією INT 21h

Вихід: AX код помилки, якщо CF=1

DTA заповнена даними

Дана функція викликається після функції 4Eh INT 21h і знаходить наступний файл, що відповідає параметрам пошуку, заданим при визові 4Eh INT 21h.

В AH заноситься номер функції, в регістрову пару DS:DX - адреса даних, повернутих попередньою функцією.

Функція повертає в AX код помилки, якщо вона не відбулась, або поміщує в буфер DTA дані про файл, що відповідає узагальненому імені і атрибуту.

Приклад:

mov ah, 4Eh ; в аh номер функції першого пошуку

mov dx, affset mask ; в dx зміщення маски

mov cx, 10h

int 21h

jc end

@@01:

mov ah, 4Fh ; в аh номер функції наступного пошуку

int 21h

jnc @@01

end:

Приклад демонструє перегляд каталогу на наявність файлів, що відповідають масці, заданої змінною mask. В буфері DTA залишається опис останнього знайденого файлу.

2.2.2. Інші функції переривання INT 21h, що необхідні для використання у програмі, що розробляється

2h функція INT 21h [6]

Вхід: AH 02h

DL код символу, що виводиться на вивід

Вихід: символ на екрані

В AH поміщується код функції, в DL код символу, що необхідно вивести на екран.

Слід відмітити, що при наявності в DL коду 8 (ASCII код Backspace) функція переміщує курсор вліво на одну позицію.

Для виконання переходу на новий рядок слід послідовно вивести символи із кодами 13 і 10 на екран [5].

Приклад:

mov ah, 2 ; номер функції

mov dl, 13 ; вертикальна табуляція

int 21h

mov dl, 10 ; зсув каретки

int 21h

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

40h функція INT 21h [6]

Вхід: AH 40h

BX описувач файлу

DS:DX адреса буфера, що містить дані, що записуються

CX число байт, що записуються

Вихід: AX код помилки, якщо CF=1

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

Дана функція записує CX байт даних в файл, або пристрій, заданий описувачем в BX. В AH поміщується номер функції, BX містить описувач [6]:

0 Стандартний пристрій вводу (звичайна клавіатура)

1 Стандартний пристрій виводу (звичайний екран)

2 Стандартний пристрій помилок (CON-екран)

3 Стандартний пристрій AUX (COM 1)

4 Стандартний принтер (LPT1)

Регістрова пара DS:DX адресується на буфер. В CX міститься кількість записуваних байт.

Функція повертає в AX код помилки при умові, що CF встановився в 1, або кількість реально зчитаних байтів в AL.

Для нас дана функція цікава як інструмент для виводу даних на екран, тому в BX має бути занесено 1.

Приклад:

mov ah, 40h ; код функції

mov bx, 1 ; вивід на екран

mov dx, offset sstring ; в dx зміщення рядка виводу

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

int 21h

Даний фрагмент коду виводить на екран рядок символів, що містяться в змінній sstring.

4Ch функція INT 21h [6]

Вхід: AH 4Ch

AL код виходу

Вихід: не має

Функція завершення програми (EXIT). Повертає управління від породженого процесу його батьківському процесу. Встановлює код виходу (його можна опитати функцією WAIT (4Dh)).

В AХ міститься номер функції, в AL - код виходу:

0 нормальне завершення

1 завершення через Ctrl-Break (INT 23h)

2 завершення по критичній помилці пристрою (INT 24h)

3 завершення через функцію KEEP (31h)

Приклад:

mov ax, 04ch ; в al - код виходу

int 21h ; в ah - номер функції

Даний фрагмент коду задає нормальне завершення роботи програми (повертається код виходу - 0).

3. Розробка задачі на мові асемблер

3.1. Допоміжні процедури

Очевидно, що основна програма потребує допоміжні процедури для отримання необхідних параметрів, які задає користувач в командному рядку при визові програми. Серед них: процедури вводу/виводу даних на консоль, обробки ASCII рядків, а також перетворення числових даних у ASCII формат для подальшого їх виведення на екран. Для цього були розроблені спеціальні модулі PARAMS.asm, STRIO.asm та BINASC.asm, які містять необхідні процедури. Розглянемо їх окремо.

3.1.1. Модуль PARAMS.asm

Традиційно, програми MS DOS дозволяють користувачу вводити в командному рядку одне чи більше імен файлів і інші дані. Для нас це цікаве можливістю одразу при визові основної програми DR.exe задавати шлях до директорії та маску файлів, які ми бажаємо вивести на екран [7].

Наприклад:

c > DR c:\windows\*.sys

Тобто даний ввід має викликати програму DR.exe, яка виведе усі файли із розширенням .sys, які знаходяться за адресою c:\windows. Мова асемблера не дає нам вбудованих механізмів реалізації даної можливості, тому виникає необхідність розробки власного програмного модуля для роботи із командним рядком.

При завантаженні exe-файлу command.com створює в пам'яті PSP блок (256 байт), у якому, серед іншої інформації, містить текст, який йде після імені програми (хвіст команди). Перед початком виконання програми адреса PSP міститься в регістровій парі ds:es. Хвіст команди починається зі зміщення 80h (до FFh) і займає 128 байт, при чому перший символ знаходиться за зміщенням 81h, а в 80h міститься кількість символів хвоста команди [4, 6].

Ідея модуля PARAMS.asm в тому, що створюється власний 128-ми байтовий буфер, в який (за допомогою функції GetParams) копіюється хвіст команди, а потім виконується обробка отриманих даних за допомогою функції GetOneParam (отримання адреси параметра за номером) і ParamCount (отримання кількості параметрів).

Параметри в хвості команди розділені пробілами, останній символ - символ повернення каретки.

На основі сказаного було розроблено наступний програмний модуль:

IDEAL

MODEL small

TailLen EQU 0080h ; зміщення байта із довжиною рядка

; параметрів

CommandTail EQU 0081h ; зміщення першого символу рядка

; параметрів

DATASEG

numParams DW ? ; кількість параметрів

params DB 128 DUP (?) ; буфер на 128 байт для хвоста команди

CODESEG

PUBLIC ParamCount, GetParams, GetOneParam

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

; Separators внутрішня процедура для перевірки на пробіли, табуляцію,

; повернення каретки

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

; Вхід ds:si адреса символу, що перевіряється

; Вихід ZF=1 символ є пробілом, табуляцією чи поверненням каретки

ZF=1 символ не є роздільником

; Регістри не змінюються

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

PROC Separators

push ax ; збереження у стеку ax

mov al, [si] ; в al поміщується символ із ds:si

cmp al, 020h ; порівняння al із пробілом

je @@10 ; якщо так, то перехід

cmp al, 009h ; порівняння al із табуляцією

je @@10 ; якщо так, то перехід

cmp al, 00Dh ; порівняння al із символом повернення

; каретки

@@10:

pop ax ; відновлення ax

ret ; повернення до викликаючої програми

ENDP Separators

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

; ParamCount повертає кількість параметрів у хвості команди

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

; Вхід не має

; Вихід CX кількість параметрів командного рядка

; Регістри CX

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

PROC ParamCount

mov cx, [numParams] ; отримати значення змінної numParams

ret ; повернення до викликаючої програми

ENDP ParamCount

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

; GetParams занесення параметрів командного рядка DOS у буфер

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

; Вхід ds префікс сегмента програми (PSP) (адресує PSP, якщо його

; не змінювали)

; es сегмент даних програми

; Вихід [params] початок буфера заповненого даними

; [numParams] кількість параметрів

; ds сегмент даних програми

; Регістри al, bx, dx, si, di, ds

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

PROC GetParams

;------Ініціалізація cx і індексних регістрів si і di

push ax ; збереження регістрів

push bx

push dx

push si

push di

xor ch, ch ; обнуління верхньої половини cx

mov cl, [ds:TailLen] ; в cx довжина параметрів

inc cx ; включити символ повернення каретки

mov si, CommandTail ; адреса параметрів поміщується в si

mov di, offset params ; адреса призначення поміщується в di

; ------Пропуск початкових пробілів і табуляції

@@10:

call Separators ; пропуск пробілів і табуляції

jne @@20 ; перехід, якщо пробілів і табуляції не має

inc si ; пропуск символу

loop @@10 ; цикл, доки не скінчиться обробка, або cx=0

; ------Копіювання параметрів рядка в буфер params

@@20:

push cx ; збереження cx у стеку

jcxz @@30 ; пропуск копіювання, якщо cx=0

cld ; збільшення на 1 si і di

rep movsb ; копіювання cx байтів із ds:si в es:di

; ------Перетворення пробілів в 0 і встановлення numParams

@@30:

push es

pop ds ; ds = es

pop cx ; відновлення cx (довжину)

xor bx, bx ; обнуління bx, лічильник параметрів

jcxz @@60 ; пропуск циклу якщо cx=0 (довжина)

mov si, offset params ; поміщення адреси параметрів в si

@@40:

call Separators ; перевірка на пробіли, табуляцію,

; повернення каретки

jne @@50 ; перехід, якщо не знайдено роздільник

mov [byte ptr si], 0 ; заміна роздільника на 0

inc bx ; збільшення лічильника кількості

; параметрів

@@50:

inc si ; переміщення указника на наступний

; символ

loop @@40 ; виконувати в циклі, доки cx ? 0

@@60:

mov [numParams], bx ; збереження в numParams кількість

; параметрів

pop ax ; відновлення регістрів

pop bx

pop dx

pop si

pop di

ret ; повернення до батьківської програми

ENDP GetParams

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

; GetOneParam отримати адресу параметра за номером

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

; Вхід cx номер параметра (має бути менше значення в numParams)

; Вихід di зміщення ASCII рядка із потрібним параметром

; Регістри di

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

PROC GetOneParam

push ax ; збереження регістрів ax і cx

push cx

xor al, al ; обнуління al (ініціалізація шуканого

; значення 0)

mov di, offset params ; адреса параметрів рядка

jcxz @@99 ; якщо номер параметра (cx) дорівнює 0,

; то вихід

cmp cx, [numParams] ; порівняння cx із кількістю параметрів

jae @@99 ; вихід, якщо передано неіснуючого

; параметру

cld ; автоматичне збільшення di

@@10:

scasb ; пошук нульового обмежувача

jnz @@10 ; повтор, доки не знайдено 0

loop @@10 ; повтор, доки в cx не буде 0

@@99:

pop cx ; відновлення регістрів cx, ax

pop ax

ret ; повернення до викликаючої програми

ENDP GetOneParam

END

Таким чином, програмний модуль PARAMS.asm є зручним інструментом для реалізації роботи із командним рядком і буде використаний в основній програмі.

3.1.2. Модуль STRIO.asm

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

З цих міркувань було розроблено програмний модуль STRIO.asm, в якому міститься п'ять спеціальних функцій: StrLength (визначає кількість символів, записаних в ASCII рядку), дві функції виводу ASCII-рядків на екран - StrWrite і StrWrite2, а також функцію NewLine (перехід на новий рядок) та WriteSimv (виводить на екран заданий символ необхідну кількість разів).

Слід зазначити, що даний програмний модуль не містить функцій читання із консолі в рядок, однак основна програма отримує дані із PSP DOS-а і опрацьовує вже створені дані, а тому не потребує якихось додаткових вказівок через консоль від користувача, всі необхідні специфічні дані (наприклад, маска файлів) користувач може задати в командному рядку при визові основної програми.

Код програмного модуля STRIO.ASM приведений нижче:

IDEAL

MODEL small

ASCnull EQU 0 ; ASCII нуль

ASCcr EQU 13 ; ASCII символ повернення каретки

ASClf EQU 10 ; ASCII символ вертикальної табуляції

; (прогону рядка)

CODESEG

PUBLIC StrLength, StrWrite, StrWrite2, NewLine, WriteSimv

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

; StrLength підраховує кількість ненульових символів в рядку

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

; Вхід di адреса ASCII рядка

; Вихід cx кількість ненульових символів в рядку

; Регістри cx

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

PROC StrLength

push ax ; зберегти у стеку змінювані

push di ; регістри ax, di

xor al, al ; в al поміщується шуканий символ 0

mov cx, 0ffffh ; в cx максимальна глибина пошуку

cld ; автоматичне збільшення di

repnz scasb ; шукати al, доки [di] або cx не стане 0

not cx ; логічне заперечення cx

dec cx ; зменшення cx на 1 - довжина рядка

pop di ; відновлення регістрів

pop ax

ret ; повернення до викликаючої програми

ENDP StrLength

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

; StrWrite вивід рядка на стандартний пристрій виводу

; StrWrite2 вивід заданої кількості символів рядка на консоль

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

; Вхід di адреса ASCII рядка

; cx кількість записуваних символів (для StrWrite2)

; Вихід символьний рядок виводиться на стандартний пристрій

; виводу

Регістри cx (для StrWrite)

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

PROC StrWrite

call StrLength ; встановити в cx довжину рядка

PROC StrWrite2 ; друга змінна точка входу

push ax ; збереження змінюваних регістрів

push bx

push dx

mov bx, 1 ; задання стандартного пристрою виводу

mov dx, di ; адресація ASCII рядка в ds:dx

mov ah, 40h ; в ax номер функції, що виконує запис

; в файл або на пристрій виводу

int 21h ; виклик 21 переривання DOS

pop dx ; відновлення збережених регістрів

pop bx ; із стеку

pop ax

ret ; повернення до визиваючої програми

ENDP StrWrite2

ENDP StrWrite

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

; NewLine перейти на новий рядок на стандартному пристрої виводу

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

; Вхід не має

; Вихід на пристрій виводу посилаються символи повернення

; каретки і прогону рядка

; Регістри не має

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

PROC NewLine

push ax ; збереження регістрів у стек

push dx

mov ah, 2 ; в ah номер функції виводу символу у DOS

mov dl, ASCcr ; в dl символ повернення каретки

int 21h ; вивести символ повернення каретки

mov dl, ASClf ; в dl символ прогону рядку

int 21h ; вивести символ прогону рядку

pop dx ; відновлення регістрів із стеку

pop ax

ret ; повернення до викликаючої програми

ENDP NewLine

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

; WriteSimv вивід на стандартний пристрій виводу заданий символ

; визначену кількість разів

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

; Вхід dl код символу

; cx кількість виводів символу

; Вихід на пристрій виводу задану кількість разів посилається

; переданий символ

;Регістри не має

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

PROC WriteSimv

push ax ; збереження регістрів

push cx

@@01:

mov ah,02 ; в ah номер функції DOS запису символу

int 21h ; вивести заданий символ

loop @@01 ; повторювати доки cx?0

pop cx ; відновлення регістрів

pop ax

ret ; повернення до викликаючої програми

ENDP WriteSimv

END

Функції, надані програмним модулем STRIO.asm, є зручними і простими інструментами виводу інформації на стандартний пристрій виводу і будуть використані в основній програмі.

3.1.3. Модуль BINASC.asm

Мови високого рівня надають програмісту можливість безпосередньо зчитувати і виводити числові значення. Нажаль, мова асемблера таких інструментів не має. В основній програмі значна частина роботи пов'язана з виводом із деякого буфера даних на екран . Однак дані в буфері зберігаються у вигляді двійкових слів того чи іншого типу. З'являється необхідність перетворення двійкових даних у ASCII-рядки, щоб у подальшому їх можна було вивести на екран. Дану проблему і покликані вирішити функції модуля BINASC.asm. Модуль складається із чотирьох функцій: допоміжних функцій HexDigit (перетворення чотирьохбітового значення у ASCII-цифру) і NumToAscii (перетворення беззнакового двійкового числа у ASCII-рядок), а також двох функцій BinToAscHex і BinToAscDec, які встановлюють систему числення і викликають вищезгадані функції.

Слід зазначити, що функція BinToAscDec зручна для перетворення і подальшого виводу чисел типу "слово" у вигляді десяткового числа.

Функцію BinToAscHex можна використовувати для виводу подвійного слова у вигляді шістнадцятирічного числа, послідовно перетворюючи і виводячи спочатку молодші два, а потім і старші байти, на екран.

Це дозволяє вирішити проблему обробки чотирьохбайтових даних, оскільки звичайні регістри є двохбайтовими і перетворення такого числа у, наприклад, десяткове представлення є проблематичним.

Код програмного модуля BINASC.asm приведено нижче:

IDEAL

MODEL small

ASCnull EQU 0 ; нульовий ASCII-символ

DATASEG

CODESEG

PUBLIC HexDigit, NumToAscii

PUBLIC BinToAscHex, BinToAscDec

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

; HexDigit перетворює чотирьохбітове значення в ASCII-цифру

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

; Вхід dl значення від 0 до 15

; Вихід dl шістнадцятирічний еквівалент ASCII-цифри

; Регістри dl

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

PROC HexDigit

cmp dl, 10 ; перевірка, чи є dl < 10

; (тобто менше шістнадцятирічного 'А')

jb @@10 ; якщо так, то перехід

add dl, 'A'-10 ; перетворити в A, B, C, D, E або F

ret ; повернення до викликаючої програми

@@10:

or dl, '0' ; перетворити в числа від 0 до 9

ret ; повернення до викликаючої програми

ENDP HexDigit

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

; NumToAscii перетворює беззнакове двійкове значення у ASCII-рядок

; згідно із заданою системою числення

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

; Вхід ax двохбайтове число, яке перетворюється

; bx основа системи числення результату (2 - двійкова,

; 10 - десяткова, 16 - шістнадцятирічна)

; cx мінімальна кількість цифр, що виводяться

; di адреса рядка для результату

; Вихід di вказує на новостворений рядок із результатом

; Регістри не має

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

PROC NumToASCII

push dx ; збереження змінюваних регістрів

push di

push si

xor si, si ; встановити лічильник цифр у стеку в 0

jcxz @@20 ; якщо cx = 0, то перехід

@@10:

xor dx, dx ; обнуління dx; ax розширюється до

; 32-х-бітного dxax

div bx ; в ax результат ділення на bx, в dx залишок

call HexDigit ; перетворення числа в dl в ASCII-пару

push dx ; збереження цифри в стеку

inc si ; збільшення лічильника цифр у стеку

loop @@10 ; виконувати цикл, доки не оброблена

; мінімальна кількість цифр

@@20:

inc cx ; встановити cx=1, якщо не усі цифри

; оброблені

or ax, ax ; перевірка ax на обробку всіх цифр

jnz @@10 ; якщо ax?a, продовження перетворень

mov cx, si ; в cx поміщується кількість цифр у стеку

jcxz @@40 ; пропуск наступного циклу, якщо cx=0

cld ; автоматичне збільшення di

@@30:

pop ax ; в ax поміщується цифра із стеку

stosb ; запис цифри в рядок і збільшення di

loop @@30 ; в циклі вивід cx цифр

@@40:

mov [byte di], ASCnull ; записується 0 у кінець рядка

pop si ; відновлення регістрів

pop di

pop dx

ret ; повернення до викликаючої програми

ENDP NumToASCII

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

; BinTo AscHex перетворює двійкове значення в шістнадцятирічні

; ASCII-рядки

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

; Вхід ax двохбайтове значення, що перетворюється

; cx мінімальна кількість чисел, що виводиться

; di адреса рядка для результату

; Вихід di вказує на рядок із сформованим результатом

; Регістри не має

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

PROC BinToAscHex

mov bx, 16 ; в bx встановити основу шістнадцятирічної

; системи числення - 16

call NumToAscii ; перетворення числа із ax в ASCII-рядок,

; на який вказує di

ret ; повернення до викликаючої програми

ENDP BinToAscHex

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

; BinTo AscHex перетворює двійкове значення в десяткові ASCII-рядки

Страницы: 1, 2


© 2010 РЕФЕРАТЫ