Всем добрый день. Давайте подведём итоги, что мы узнали за прошедшие уроки. А мы узнали вот что:
— Как установить прикладное программное обеспечение; — Как воспользоваться файлом помощи; — Как пользоваться отладчиком; — Как составить и скомпилировать программу на языке ассемблера.
Также, мы узнали немного о десятичной и шестнадцатеричной системах счисления и основных регистрах.
Нормально,
если что-то непонятно, да ещё и при таком быстром изучении. В
дальнейшем мы ещё раз будем останавливаться на непонятных вопросах, да и
тексты программ будут снабжены комментариями.
Сегодня мы узнаем о
циклах, операторе безусловного перехода и вызове подпрограмм.
Соответственно это операторы loop, jmp и call. Сейчас мы рассмотрим их
применение.
loop — оператор, позволяющий организовать цикл. Он использует значение регистра cx, о котором мы писали в 4-м уроке, что он является счётчиком. Допустим, нам надо 5 раз вывести строку "Hello, world". Как это будет выглядеть?
.286 CSEG segment assume cs:CSEG, ds:CSEG, es:CSEG, ss:CSEG org 100h begin: ;Всё написанное выше пока опускаем. mov cx,5 ;Устанавливаем значение
счётчика в 5.
metka: mov ah,9 ;Загружаем в регистр ah число 9 (указываем функцию). mov dx,offset helloworld ;Указываем, что за фразу мы будем выводить. int 21h ;Выводим фразу. loop metka ;Переходим на метку metka и уменьшаем cx на 1.
int 20h ;Выходим в DOS.
helloworld db 'Hello, world!$' ;Определяем переменную helloworld, доступную побайтно, с фразой ;"Hello, world!". В одинарных кавычках, после знака
"!" ставим ;знак "$".
;Завершение программы. CSEG ends end begin
Сохраняем в файле test.asm в кодировке 866, а далее ml test.asm /AT Запускаем файл test.com
(через тот же Far, естественно). Мы видим фразу "Hello, world",
написанную 5 раз. Если не успеваем её увидеть, нажимаем Ctrl+O (скрыть
панели).
Запустим отладчик: afdpro test.com. Используя
клавишу F2, посмотрите, как меняется содержимое регистров в верхнем
левом углу (для перехода к началу нажимайте F3). Для выхода из отладчика
введите в командной строке: quit.
Следующий оператор —
jmp. Это оператор безусловного перехода, кто изучал "Бейсик", знает
похожий оператор GOTO. Он также использует метки для своего "прыжка".
Рассмотрим следующую программу.
.286 CSEG segment assume cs:CSEG, ds:CSEG, es:CSEG, ss:CSEG org 100h begin: ;Всё написанное выше пока опускаем.
jmp exit ;"Прыгаем" на метку exit, не выполняя операторы ниже. mov ah,9 ;Загружаем в регистр ah число 9 (указываем функцию). mov dx,offset helloworld ;Указываем, что за фразу мы будем выводить. int 21h ;Выводим фразу.
exit: ;Метка на шаге 2. int
20h ;Выходим в DOS.
helloworld db 'Hello, world!$' ;Определяем переменную helloworld, доступную побайтно, с фразой ;"Hello, world!". В одинарных кавычках, после знака "!" ставим ;знак "$".
;Завершение программы. CSEG ends end begin Сохраняем в файле test.asm в кодировке 866, а далее ml test.asm /AT Запускаем файл test.com. Программа успешно завершает свою работу,
но ничего не выводит на экран. Думаю, с этим понятно.
call — оператор вызова подпрограммы. Сама подпрограмма оформляется так:
Начало — NameProg proc, где NameProg — метка начала подпрограммы, proc — оператор; Конец — ret и в следующей строчке NameProg endp Почему
оператора два, рассмотрим чуть позже. Для усвоения примера возьмём
прошлую программу, где ничего не выводится, и несколько её
модернизируем.
.286 CSEG segment assume cs:CSEG, ds:CSEG, es:CSEG, ss:CSEG org 100h begin: ;Всё написанное выше пока опускаем.
jmp exit ;"Прыгаем" на метку exit, не выполняя операторы ниже.
NameProg proc ;Начало нашей подпрограммы. mov ah,9 ;Загружаем в регистр ah число 9 (указываем функцию). mov dx,offset helloworld ;Указываем, что за фразу мы будем выводить. int 21h ;Выводим фразу. ret NameProg endp ;Конец подпрограммы.
exit: ;Метка на шаге 2.
call NameProg ;Вызываем подпрограмму вывода, которая выводит фразу.
int 20h ;Выходим в DOS.
helloworld db 'Hello, world!$' ;Определяем переменную helloworld, доступную побайтно, с фразой ;"Hello, world!". В одинарных кавычках, после знака "!" ставим ;знак "$".
;Завершение программы. CSEG ends end begin
Что же получилось? Командой jmp exit
мы "прыгаем" в конец программы. Сразу после этого мы вызываем (call)
подпрограмму и выходим. Сама подпрограмма у нас находится выше под
командой jmp. Таким образом, теперь мы можем размещать подпрограммы в разных местах. Для
чего это нужно? Для сокращения текста программы, когда приходится много
раз применять одинаковые "куски" программ (например, для вывода
различных текстов). В последующих примерах мы закрепим это. Не забудьте
посмотреть нашу программу через отладчик (afdpro test.com)!