On-Line Библиотека www.XServer.ru - учебники, книги, статьи, документация, нормативная литература.
       Главная         В избранное         Контакты        Карта сайта   
    Навигация XServer.ru


Продвижение сайта в топ, компания - поисковое продвижение сайта www.seop.ru.




 

Создание циклов.

© oleg

Что такое цикл? Допустим, нам нужно выполнить некоторый код программы несколько раз. Возьмем, к примеру, вывод строки функцией 09h прерывания 21h:

Пример 1.

mov ah,9

mov dx,offset Str

int 21h

mov ah,9

mov dx,offset Str

int 21h

mov ah,9

mov dx,offset Str

int 21h

Этот участок кода выведет 3 раза на экран некую строку Str. Код получается громоздким, неудобно читать. Размер программы разрастается... Для выполнения подобных примеров используется оператор loop (вспоминаем, как мы оформляем новые операторы):

Команда

Перевод (с англ.)

Назначение

Процессор

LOOP метка loop - петля Организация циклов 8086

Количество повторов задается в регистре CX (счетчик). Вот как можно использовать этот оператор на практике (изменим пример 1):

Пример 2:

(1) mov cx,3

(2) Label_1:

(3) mov ah,9

(4) mov dx,offset Str

(5) int 21h

(6) loop Label_1

(7) ...

В строке (1) загружаем в CX количество повторов (отсчет будет идти от 3 до 0). В строке (2) создаем метку (Label - метка). Далее (строки (3)-(5)) выводим сообщение. И в строке (6) оператор loop уменьшает на единицу CX и, если он не равен нулю, переходит на метку Label_1 (строка (2)). Итого строка будет выведена на экран три раза. Когда программа перейдет на строку (7), регистр CX будет равен нулю. В результате код программы уменьшается почти в три раза по сравнению с Примером 1.

Удобно? Без вопросов!

Тренироваться будем на практике, а теперь следующий оператор:

Команда

Перевод (с англ.)

Назначение

Процессор

JMP метка jump - прыжок Безусловный переход 8086

Команда jmp просто переходит на указанную метку в программе:

(1) mov ah,9

(2) mov dx,offset Str

(3) int 21h

(4) jmp Label_2

(5)

(6) add cx,12

(7) dec cx

(8) Label_2:

(9) int 20h

В результате строки (5) - (7) работать не будут. Программа выведет сообщение на экран, а затем jmp перейдет к строке (8), после чего программа завершится.

Команда

Перевод (с англ.)

Назначение

Процессор

DEC приемник decrement - декремент Уменьшение на 1 8086

Оператор dec уменьшает значение приемника на 1:

mov ah,12 ---> AH=12

dec ah ---> AH=11

С помощь данного оператора можно также создавать циклы, которые будут работать быстрее оператора loop. Следующий пример будет работать также, как Пример 2, только чуть-чуть быстрее:

Пример 3:

(1) mov cx,3

(2) Label_1:

(3) mov ah,9

(4) mov dx,offset Str

(5) int 21h

(6) dec cx

(7) jnz Label_1

Не обращайте внимание на строку (7). Мы ее рассмотрим позже. Я привел этот пример для того, чтобы показать, что один и тот же прием в Ассемблере можно выполнить разными операторами. И чем лучше программист владеет ими, тем компактнее и быстрее программа будет работать. Поэтому и получается, что разные программисты пишут на одном языке, но скорость и объем программы разные. В процессе обучения, я буду также учить вас оптимизировать программы.


Программка для практики.

Усовершенствуем программу из предыдущей рассылки, которая выводила в верхний левый угол "рожицу" прямым отображением в видеобуфер.

(1) CSEG segment

(2) org 100h

(3) Begin:

(4) mov ax,0B800h

(5) mov es,ax

(6) mov di,0

(7) mov al,1

(8) mov ah,31

(9) mov cx,2000

(10)

(11) Next_face:

(12) mov es:[di],ax

(13) add di,2

(14) loop Next_face

(15)

(16) mov ah,10h

(17) int 16h

(18) int 20h

(19) CSEG ends

(20) end Begin

Уфф! Длинная получилась. Прежде чем читать описание программы, попробуйте сами разобраться, что в итоге получится. Поверьте, это принесет вам пользу. Все ведь очень просто!

Теперь описание программы.

Строки с (1) по (10) и с (15) по (20) вы уже знаете. Объясню только новое.

Строка (11) - это метка, как бы "голова" нашего цикла. Строка (14) - "хвост" цикла. Все, что находится в пределах строк (10) - (14), является циклом. Сам цикл будет повторяться 2000 раз, для чего мы и заносим в CX число 2000 (строка (8)).

В строке (12) записываем в видеобуфер (0B800:DI) число в AX (это символ (строка (7) и атрибут (строка (8)). Итак, первый символ занесли. Что делаем дальше?

Дальше увеличиваем регистр DI на 2 для того чтобы перейти к адресу следующего символа. Почему на 2? Дело в том, что в видеобуфере один символ занимает 2 байта: сам символ и его атрибут. Т.к. символ у нас в AL, а атрибут в AH, и мы загрузили уже эти два байта в строке (12), то и увеличиваем DI (смещение) на 2.

DI теперь указывает на адрес для следующего символа. Осталось уменьшить счетчик (CX) на 1 и повторить. Что мы, собственно, и делаем в строке (14).

Все! Обратите внимание на скорость вывода символов при запуске программы.

Еще раз напоминаю: пожалуйста, печатайте все программы сами! Так вы быстрее освоите Ассемблер!



Литература по Assembler