Иллюстрированный самоучитель по Assembler

Использование подпрограмм

Общая идея использования подпрограмм очевидна: если в программе требуется многократно выполнять один и тот же фрагмент, его можно оформить в виде подпрограммы и вызвать по мере необходимости. Если подпрограмма не требует для своего выполнения никаких параметров и не должна возвращать в основную программу результат своей работы, то дело ограничивается оформлением текста подпрограммы в виде процедуры, завершающейся командой ret, и вызовом этой процедуры с помощью команды call. Как уже отмечалось ранее, подпрограмма может и не образовывать процедуру, а быть просто частью основной программы. Важно только, чтобы у нее была входная метка, и чтобы она завершалась командой ret.

В следующем примере подпрограмма delay используется для включения в основной текст программы программных задержек фиксированной величины.

Пример 3.8. Вызов подпрограммы без параметров.

code segment
assume cs:code,ds:data
delay proc; Процедура-подпрограмма
push CX; Сохраним СХ основной программы
mov CX,2000; Счетчик внешнего цикла
del1: push CX; Сохраним его
mov CX,0; Счетчик внутреннего цикла
del2: loop del2; Внутренний цикл (64К шагов)
pop CX; Восстановим внешний счетчик
loop del1; Внешний цикл (2000 шагов)
pop CX; Восстановим СХ программы
ret; Возврат в подпрограмму
delay endp
main proc
mov AX,data; Настроим DS
mov DX,AX; на сегмент данных
mov AH,09h; Функция вывода на экран
mov DX,offset npl1; Адрес первой строки
mov CX,3; Будем выводить строки в цикле
cntrl1: int 21h; Вызов DOS
cal1 delay; Вызов подпрограммы задержки
add DX,msg_len; Прибавим к смещению длину строки
loop cntrl; Цикл вызовов DOS
mov AX,4C00h; Завершение программы
int 21h
main endp
code ends
data segment
msg1 db "Процесс стартовал",13.10,'$'
msg_len=$-msg1
msg2 db "Процесс идет",13.10,'$'
msg3 db "Процесс завершается",13.10,'$'
data ends
stk segment stack
dw 128 dup(')
stk ends
end main

В тексте программы сначала описана процедура-подпрограмма, затем основная программа. Как уже отмечалось, порядок их описания роли не играет; важно только, чтобы в завершающей директиве окончания трансляции end был указан в качестве точки входа адрес основной программы (main в нашем примере).

Подпрограмма реализует задержку с помощью вложенных циклов с командой loop, использующей в качестве счетчика шагов регистр СХ. В основной программе этот регистр используется для организации цикла вывода трех строк. Поэтому первое, что должна сделать подпрограмма – это сохранить содержимое регистра СХ, для чего естественно использовать стек. Перед завершающей командой ret регистр СХ должен быть восстановлен. Фрагмент, реализующий задержку, был описан ранее, в разделе 3.2.

Основная программа выводит на экран с помощью функции 09h три строки текста. Для упрощения программы, а также чтобы продемонстрировать некоторые приемы программирования, вывод строк реализован в цикле. Строки сделаны одной длины, и модификация смещения к очередной строке выполняется прибавлением к содержимому регистра DX длины строки. Полезно обратить внимание на организацию цикла в основной программе. В цикл, помимо команды вызова подпрограммы задержки и предложения, модифицирующего регистр DX, включена лишь команда int 21h. Регистр АН с номером функции заново не настраивается. Это и не нужно, так как DOS, выполняя затребованную операцию, первым делом сохраняет все регистры программы, а перед возвратом в программу их восстанавливает.

Поэтому, вызывая функции DOS (или BIOS) можно не заботиться о сохранении регистров – их содержимое система на разрушает. Надо только иметь в виду, что многие функции DOS и BIOS после своего завершения возвращают в программу некоторую информацию (число реально введенных символов, доступный объем памяти, номер видеорежима и т.п.) Обычно эта информация возвращается в регистре АХ, однако могут использоваться и другие регистры или их сочетания. Поэтому, обращаясь в программе к системным функциям, необходимо ознакомиться с их описанием и, в частности, посмотреть, какие регистры они могут использовать для возвращаемых значений.

Запустив программу, можно убедиться в том, что строки текста появляются на экране через заметные промежутки времени.

Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.