Лабораторная работа №4 организация программ с процедурами. Обработка массивов Теоретические сведения
Организация подпрограмм (процедур).
Некоторые аспекты применения подпрограмм были рассмотрены в лабораторной работе №3. Рассмотрим организацию и применение подпрограмм более подробно.
Если программа получается относительно громоздкой, ее бывает целесообразно разить на небольшие подпрограммы (процедуры). В общем случае программа состоит из одной или нескольких взаимосвязанных процедур. Использование процедур преследует две основные цели: во-первых, уменьшение объема программы путем повторного использования ее частей, и, во-вторых, облегчение разработки программы за счет разбиения общей задачи программы на подзадачи и решения каждой из подзадач по отдельности.
Процедура приводится в действие командой вызова, имеющей формат
call имя
где имя – метка, определяющая начальный адрес процедуры. Эта метка называется точкой входа процедуры. При выполнении команды САLL адрес возврата заносится в стек, а затем управление передается подпрограмме. Процедура выполняется до тех пор, пока не встретится команда RET, которая извлекает из стека адрес возврата и управление передается команде вызывающей программы, следующей за командой вызова.
Для организации процедур служат директивы PROC, которая отмечает точку входа в процедуру, и ENDP, которая отмечает конец процедуры:
имя proc [тип]
…
; тело процедуры
…
ret
имя endp
В обеих директивах должно использоваться одно и то же имя процедуры (точка входа). Справа от PROC может указываться тип процедуры: NEAR или FAR (по умолчанию принимается NEAR). Если указан тип NEAR, то предполагается, что процедура находится в том же сегменте кода, что и все команды САLL, ее вызывающие. В этом случае команда САLL помещает в стек только 16-битное смещение адреса следующей команды, которое затем восстанавливается командой RET. Если процедура имеет тип FAR, то предполагается, что процедура и ее вызовы находятся в разных сегментах кода, и в стеке при ее вызове запоминается база и смещение точки входа относительно базы, то есть содержимое регистров CS и IP. Команда RET в процедуре типа FAR восстанавливает сначала смещение для загрузки в регистр IP, а затем адрес сегмента для загрузки в регистр CS. Передача данных между процедурами может осуществляться по разному:
через регистры общего назначения;
через стек;
через общую область данных;
через внешний файл.
В приведенных далее примерах используется первый способ – передача параметров через регистры.
В виде процедур часто оформляются участки программы, выполняющие какие-либо служебные, вспомогательные задачи и управление которым передается неоднократно. Главная часть программы, тем не менее, тоже может быть оформлена с помощью директив PROC и ENDP. Однако, так как передача управления главной процедуре будет осуществляться не командой CALL, вместо команды RET необходимо вызвать функцию DOS завершения программы. Имя главной процедуры можно использовать при указании точки входа в директиве конца программы END.
Приведем структуру программы с двумя процедурами.
sseg segment stack
dw 32 dup (?)
sseg ends
dseg segment
n dw 7
min dw ?
...
dseg ends
cseg segment
assume ds:dseg, cs:cseg, ss:sseg
start proc far
push ds
mov ax,0
push ax
mov ax,dseg
mov ds,ax
call main
ret
start endp
main proc near
...
; тело процедуры – обработка данных
ret
main endp
cseg ends
end start
Данная программа содержит три сегмента: sseg – сегмент стека, dseg – сегмент данных и cseg – сегмент команд. Последний, в свою очередь, состоит из двух процедур. Процедура start вызывается непосредственно операционной системой и имеет тип FAR (это объясняется тем, что в среде MS DOS любая прикладная программа рассматривается как подпрограмма). Она реализует некоторые стандартные действия, которые в последующем обеспечивают благополучное завершение программы, и загружает в сегментный регистр ds базовый адрес сегмента данных dseg. Наконец, процедура start вызывает процедуру main, где и реализуется конкретный алгоритм обработки данных.
Далее приведена структура той же программы, но уже с использованием упрощенного описания сегментов.
.model small
.stack 32
.data
n dw 7
min dw ?
...
.code
start proc far
push ds
mov ax,0
push ax
.startup
call main
ret
start endp
main proc near
...
; тело процедуры – обработка данных
ret
main endp
end start