 |
::
Меню :: |
 |
|
|
 |
::
Друзі :: |
 |
|
|
 |
::
Лічильники :: |
 |
|
|
|
Обробка рядків
Для роботи з рядками, або ланцюжками символів або чисел (тобто просто кажучи,
з масивами довільних даних) в МП передбачений ряд спеціальних команд:
movs - пересилка рядка;
cmps - порівняння двох рядків;
seas - пошук в рядку заданого елементу;
lods - завантаження акумулятора (регістрів AL або АХ) з рядка;
stos - запис елементу рядка з акумулятора (регістрів АХ або
AL).
Ці команди
дуже зручні, проте їх використання зв'язане з деякими труднощами, оскільки
процесор, виконуючи ці команди, неявним чином використовує ряд своїх регістрів.
Тільки якщо всі ці регістри настроєні належним чином, команди виконуватимуться правильно.
В результаті включення в програму пропозиції з командою, наприклад,
movs, вимагає
інший раз 6-7 додаткових пропозицій, в яких здійснюється підготовка
умов для правильного виконання цієї команди.
Хоча команди обробки рядків, як правило, включаються в програму без
явної вказівки операндів, проте кожна команда, насправді, використовує два
операнди. Для команд seas і stos операндом-джерелом служить акумулятор, а
операнд-приймач знаходиться в пам'яті. Для команди
lods, навпаки, операнд-джерело
знаходиться в пам'яті, а приймачем служить акумулятор. Нарешті, для команд movs
і cmps обидва операнди, і джерело, і приймач, знаходяться в пам'яті.
Всі
дані команди, виконуючи різні дії, підкоряються однаковим правилам,
перерахованим нижче. Операнди, що знаходяться в пам'яті, завжди адресуються
одноманітно: операнд-джерело через регістри
Ds:si, а операнд-приймач через
регістри Es:di. При одноразовому виконанні команди обробляють тільки один
елемент, а для обробки рядка команди повинні передувати одним з префіксів
повторення. В процесі обробки рядка регістри SI і DI автоматично зміщуються
по рядку вперед (якщо прапор DF = 0) або назад (якщо прапор DF = 1), забезпечуючи
адресацію подальших елементів. Кожна команда має модифікації для роботи
з байтами або словами (наприклад, movsb і movsw).
Таким чином, для правильного виконання команд обробки рядків необхідно
(у загальному випадку) заздалегідь набудувати регістри Ds:si і
Es:di, встановити
або скинути прапор DF, занести в СХ довжину оброблюваного рядка, а для команд
seas і stos ще помістити операнд-джерело в регістр АХ (або AL при роботі з
байтами).
Проте сама операція, після всього цього налаштування, здійснюється однією командою,
яка зазвичай навіть не містить операндів, хоча може мати префікс повторення.
Варто
підкреслити, що рядки, що обробляються даними командами, можуть
знаходитися в будь-якому місці пам'яті: у полях даних програми, в системних областях
даних, в ПЗП, у відеобуфері. Наприклад, за допомогою команди movs можна скопіювати
масив даних з однієї масивної змінної в іншу, а можна переслати сторінку
тексту на екран терміналу. Розглянемо декілька прикладів використання команд
обробки рядків, обмежившись лише тими фрагментами програм, які мають
відношення до даного питання.
Приклад 3-6. Читання з ПЗУ BIOS
дати його випуску
;У
програмному сегменті
main
proc
mov
Ax,0f000h ;Занесем у DS
mov
Ds,ax ;Сегментный
адреса ПЗП BIOS
mov
Si,0fff5h ;Смещение
до того, що
цікавить нас полю
mov
Ax,data ;Настроим
RS
mov
Rs,ax ;на
сегмент даних програми
mov
Di,offset bios ;Смещение до поля для зберігання дати
mov
Cx,8
;Перенести 8 байт
cld
;Движение по рядку вперед
rep
movsb
;Перенос байтів
;Виведемо
отриману інформацію на екран
mov
Ax,data ; Тепер
набудуємо DS
mov
Ds,ax ;на
сегмент даних програми
mov
Ah,40h ;Функция
виводу
mov
Bx,1
;Дескриптор екрану
mov
Cx,8
;Вывести 0 байт
mov
Dx,offset bios ;Смещение у рядку
int
21h
; Виклик DOS
;У
сегменті даних
bios
db 8 dup (') ;Поле для зберігання
дати
Відомо, що в ПЗП BIOS,
сегментна
адреса якого складає F000h (див. мал. 1.5), разом з програмами управління
апаратурою комп'ютера, зберігаються ще і деякі ідентифікатори. Так,
у восьми байтах ПЗП, починаючи з адреси F000h:fffsh, записана в кодах ASCII дата
розробки ПЗП. У прикладі 3.6 виконується читання цієї дати, збереження її
в пам'яті і вивід на екран для контролю. Оскільки дата, що цікавить нас, зберігається
в ПЗУ BIOS в кодах ASCII, ніяких перетворень вмісту цієї ділянки ПЗП
перед виводом на екран не потрібні.
У програмі здійснюється налаштування всіх необхідних для
виконання команди movs регістрів (Ds:si, Es:di, CX і прапора DF) і однією командою movsb
з префіксом rep вміст необхідної ділянки ПЗП переноситься
в полі bios.
Перенесення рядка байтами підкреслює її формат (у рядку записані
байтові коди
ASCII), проте в нашому прикладі, при парному числі переносимих байтів, ефективніше
здійснити перенос по словах. У цьому варіанті команда movs фактично повторюватиметься
не 8 разів, а тільки 4. Для цього досить занести в СХ число 4 (замість 8) і
використовувати варіант команди niovsw.
Для виконання команди movs нам довелося набудувати сегментний регістр DS
на сегмент BIOS. Якщо надалі передбачається звернення до полів даних програми,
як це має місце в прикладі 3-6, в регістр DS слід занести сегментну адресу
сегменту даних. Після цього, набудувавши решту регістрів для виклику функції
40h, прочитану з BIOS рядок можна вивести на екран.
У розглянутому прикладі неявно передбачалося, що програма буде надалі
якось використовувати отриману з BIOS інформацію. Якщо завдання програми полягає
просто у виводі на екран дати випуску BIOS, то немає необхідності спочатку копіювати
цю дату з BIOS в поля даних програми, а потім виводити її на екран. Можна
було поступити набагато простіше: набудувавши регістр DS на сегмент
BIOS, а регістр
DX на адресу рядка з датою, викликати функцію 40h і вивести на екран текст безпосередньо
з сегменту BIOS. Тоді змістовна частина програми скоротиться в два рази
і набере такого вигляду:
mov
Ax,0f00h ;Настроим DS
mov Ds,ax
;на сегмент BIOS
mov
Ah,40h ;Функция
виводу
mov
Bx,1
;Дескриптор екрану
mov
Cx,8
;Вывести 8 байт
mov
Dx,0fffsh ;Смещение до дати
int
21h
;Вызов DOS
Приведений фрагмент не має
відношення до даного розділу, оскільки в нім вже немає команд обробки рядків. В той
же час він підкреслює важливість сегментних регістрів і гнучкість сегментної адресації. Функція
40h чекає знайти адресу рядка, що виводиться на екран, в регістрах Ds:dx,
і ніякі інші регістри в цьому випадку використовувати не можна. З іншого
боку, ці регістри можна набудувати на будь-яку ділянку пам'яті і вивести на екран
(а також і на принтер, у файл або в послідовний порт) дані звідки завгодно.
Розглянемо тепер приклад роботи з командами
lods і stos, які
можна використовувати як окремо, так і в парі один з одним. Ці команди дуже зручні,
зокрема, для прямого звернення до відеопам'яті.
До екрану,
як і до будь-якого іншого пристрою, що входить до складу комп'ютера, можна
звертатися трьома способами: за допомогою функцій DOS (переривання 21h), з використанням
переривання BIOS (для управління екраном використовується переривання 10h)
і, нарешті, шляхом прямого програмування апаратури, в даному випадку відеобуфера
(відеопам'яті). Функції DOS дозволяють виводити тільки чорно-білий текст
і мають ряд інших обмежень (не можна очистити екран, немає засобів позиціонування
курсора); при використанні переривання BIOS всі ці обмеження знімаються, проте
програмування за допомогою засобів BIOS вельми трудомістко; нарешті, прямий запис
у відеопам'ять, надаючи можливість виведення кольорового тексту в будь-яку точку
екрану, є процедурою дуже простій і, до того ж, підвищує швидкість виводу
(по порівнянням з використанням системних засобів) в десятки і сотні разів. Пряме
звернення до відеобуфера зручно використовувати, наприклад, в обробниках переривань,
де заборонений виклик функцій DOS і є обмеження на звернення до засобів
BIOS.
Хай по ходу програми необхідно вивести в нижній рядок екрану застережливе
повідомлення. Для цього в програму треба включити наступні пропозиції:
Приклад 3-7. Вивід на екран
прямим записом у відеопам'ять
;У
полях
даних, що адресуються через DS
msg
db 'Вимірювання закінчені'
msg_len=$-msg
;Длина рядки
;У програмному сегменті
mov
Si,offset msg
;DS:31->выводимая рядок
mov
Ax,ob800h
;Сегментный адреса відеобуфера
mov
Es,ax
;Будем адресувати через ES
mov
Di,25*80*2
;Смещение до останнього рядка екрану
mov
Cx,msg_len
;Счетчик циклу виведення символів
eld
;DF= 0, рух по рядку
; і по екрану вперед
mov
Ah,31h
;Атрибут символов-синій по
; блакитному
outher:
lodsb
;Взять символ з рядка в AL
show
; Вивід на екран символу
; з AL і його атрибуту з AH
loop
outser
; Цикл
Регістри Ds:si настроюються на
адресу почата рядка, що виводиться; регістри Es:di - на адресу необхідної позиції
у відеобуфері. У регістр СХ треба помістити довжину рядка в байтах, а прапор DF
скинути, щоб рухатися по рядку вперед. На екран виводитиметься вміст регістра
АХ, в молодшому байті якого повинен знаходитися код ASCII символу, що
виводиться, а в старшому байті - атрибут символу, тобто код кольору символу (у молодшому
півбайті) і код кольору фону (у старшому півбайті). У прикладі число 31h утворює
сині символи по бірюзовому фону. За бажання можна вибрати іншу комбінацію
квітів, вибравши її за допомогою таблиці. 3.1.
Таблиця 3.1. Коди квітів стандартної колірної палітри
Код |
Колір |
Код |
Колір |
0h |
Чорний |
8h |
Сірий |
1h |
Синій |
9h |
Блакитний |
2h |
Зелений |
10h |
Салатовий |
3h |
Бірюзовий |
11h |
Ясно-бірюзовий |
4h |
Червоний |
12h
|
Рожевий |
5h |
Фіолетовий |
13h |
Ясно-фіолетовий |
6h |
Коричневий |
14h |
Жовтий |
7h |
Білий |
15h |
Яскраво-білий |
Вибираючи кольори, слід
мати на увазі, що при стандартному налаштуванні відеосистеми для кольору фону можна
використовувати лише значення з лівого стовпця таблиці; вибір будь-якого яскравого кольору
з правого стовпця приведе у виведенню мерехтливого символу. Наприклад, атрибут символу
Bill утворює синій мерехтливий символ на бірюзовому фоні (а не синій символ на
ясно-бірюзовому фоні).
Змістовну частину циклу виводу утворюють дві команди lodsb і
stosw. Перша
команда завантажує в регістр AL код чергового символу, друга виводить його разом
з атрибутом, що зберігається в АН, на екран. При цьому після кожного виконання
команди lodsb вміст SI збільшується процесором на 1, зміщуючи адресацію до
наступного символу рядка; в той же час кожне виконання команди stosw збільшує
DI на 2 (тому що команда stosw працює із словами), зміщуючи адресацію на
екрані на 2 байт, тобто якраз до позиції наступного символу.
Приклади використання команд cmps і seas можна знайти в Додатку.
-
|
 |
::
Наша кнопка :: |
 |
|
 |
Отримати код:
|
Підтримайте наш сайт і розмістіть нашу
кнопку на своєму ресурсі. |
|
|
 |
::
Популярне :: |
 |
|
|
 |
:: Посилання :: |
 |
|
|
|