Главная -> Книги

(0) (1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) (12) (13) (14) (15) (16) (17) (18) (19) (20) (21) (22) (23) (24) (25) (26) (27) (28) (29) (30) (31) (32) (33) (34) (35) (36) (37) (38) (39) (40) (41) (42) (43) (44) (45) (46) (47) (48) (49) (50) (51) (52) (53) (54) (55) (56) (57) (58) (59) (60) (61) (62) (63) (64) (65) (66) (67) (68) (69) (70) (71) (72) (73) (74) (75) (76) (77) (78) (79) (80) (81) (82) (83) (84) (85) (86) (87) (88) (89) (90) (91) (92) (93) (94) (95) (96) (97) (98) ( 99 ) (100) (101) (102) (103) (104) (105) (106) (107) (108) (109) (110) (111) (112) (113) (114) (115) (116) (117) (118) (119) (120) (121) (122) (123) (124) (99)

длины вектора необходимо передать ей координаты X и Y, а подпрограмма должна возвратить длину вектора LENGTH. В языках высокого уровня эта подпрограмма определяется в виде VECT (X, Y, LENGTH). Фиктивные переменные в определении подпрограммы называются формальными параметрами, а переменные или значения, заменяющие их при каждом вызове, называются фактическими (действительными) переменными. Например, можно вызвать подпрограмму CALL VECT (N1, N2, RES) с соответствующими фактическими параметрами. Разработано несколько способов передачи параметров, основные из которых рассматриваются ниже.

Наиболее просто передавать параметры в фиксированные ячейки памяти, к которым могут обращаться вызывающая программа и подпрограмма. Вызывающая программа записывает в эти ячейки текущие значения параметров, а подпрограмма считывает их оттуда, обрабатывает и помещает результаты в другие фиксированные ячейки памяти, в которых они становятся доступными вызывающей программе. Передача двух параметров в ячейках PARI и PAR2 подпрограмме SUBR в процессорах СМ имеет вид:

Метка Код Операнд Комментарий

MOV VALI, PARI

MOV VAL2, PAR2 JSR R7, SUBR

Загрузка параметров в ячейки PARI и PAR2

Вызов подпрограммы

Данный способ требует резервирования ячеек памяти, предназначенных только для передачи параметров.

Чтобы упростить программирование и уменьшить объем памяти, можно передавать параметры во внутренних регистрах процессора. Например, в микропроцессоре КР580 перед вызовом подпрограммы умножения множимое загружается в регистр С, а множитель - в аккумулятор А. После вызова подпрограмма выполняет необходимые операции и формирует результат в регистрах Н, L. В процессорах СМ передача двух параметров в регистры R1 и R2 имеет следующую форму:

Метка Код Операнд Комментарий

MOV VALl.Rl

MOV VAL2, R2

JSR R7, SUBR

Загрузка значений параметров в регистры RI и R2

Вызов подпрограм-



Недостаток данного способа заключается в естественных ограничениях на число передаваемых параметров. Распределение регистров для параметров обычно приводится в заголовке - комментарии подпрограммы.

Передачу параметров в фиксированной области памяти с начальным (базовым) адресом TBLPR для микропроцессора КР580 иллюстрирует следующий фрагмент:

Метка Код Операнд Комментарий

SUBRs

LXI CALL » » » MOV

INX MOV

» » » RET

H, TBLPR SUBR

A, M

B, M

Загрузка адреса области параметров

Считывание первого

параметра Инкремент указателя Считывание , второго

параметра

Возврат

В заключение остановимся на одном интересном моменте. В простых контроллерах на базе микро-ЭВМ оперативная память может отсутствовать и, следовательно, использовать команды вызова и возврата невозможно. Но для экономии программного ПЗУ все-таки целесообразно по возможности применять подпрограммы. В такой ситуации для перехода к подпрограмме остается только команда безусловного перехода JMP (или BR), а адрес возврата приходится запоминать во внутреннем регистре процессора. Подпрограмма не должна модифицировать этот регистр, а последняя ее команда должна передавать содержимое регистра в программный счетчик. Следующий фрагмент иллюстрирует данный прием для микропроцессора КР580: Метка Код Операнд Комментарий

ADDR1:

ADDR2:

SUBR:

* » »

* » »

LXI JMP

PCHL

H, ADDRI SUBR

H, ADDR2 SUBR

; Первый вызов под-; программы

; Второй вызов под-; программы

; Начало подпрограм-мы

; Возврат



Специальные разновидности подпрограмм. Для вызывающей программы и подпрограммы характерно отношение подчиненности «ведущий - ведомый»: основная программа вызывает подпрограмму с фиксированной точкой входа; подпрограмма полностью обрабатывает переданные ей параметры и оставляет результаты в определенных ячейках; управление возвращается команде, следующей за командой вызова.

В языках высокого уровня выдерживается такое строгое отношение подчиненности, что после возврата из подпрограммы значения ее локальных переменных не определены.

Обобщением подпрограмм являются так называемые сопрограммы, при организации которых в качестве основной программы попеременно выступают две или более программ, разделяющих общие ресурсы ЭВМ. Каждая сопрограмма считает другую сопрограмму подчиненной (подпрограммой) и имеет свою контекстную среду: стек, регистры, память. Вначале управление ЭВМ осуществляет, например, сопрограмма 1, а в некоторой точке управление передается сопрограмме 2, которая начинает играть роль основной программы. С точки зрения сопрограммы 1 управление передается подчиненной программе - сопрограмме 2, но с точки зрения сопрограммы 2 происходит возврат управления из подчиненной программы - сопрограммы 1. Ситуация изменяется на противоположную, когда сопрограмма 2 передает управление сопрограмме 1. Другими словами, взаимодействие сопрограмм оказывается симметричным и напоминает диалог. Важное отличие сопрограмм от подпрограмм заключается в том, что сопрограммы сохраняют значения своих промежуточных переменных между последовательными передачами управления. Передача управления от одной сопрограммы другой инициируется оператором RESUME (возобновить) .

Сопрограммы часто применяются для обработки потока данных, включающей в себя ввод, некоторые преобразования и формирование выходов.

Другое применение сопрограмм связано с логической проверкой прикладных программ в системах проектирования. Для этого создается специальная тест-программа и взаимодействие с ней прикладной программы организуется по принципу сопрограмм. Во всех точках, где прикладная программа осуществляет ввод или вывод, управление



(0) (1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) (12) (13) (14) (15) (16) (17) (18) (19) (20) (21) (22) (23) (24) (25) (26) (27) (28) (29) (30) (31) (32) (33) (34) (35) (36) (37) (38) (39) (40) (41) (42) (43) (44) (45) (46) (47) (48) (49) (50) (51) (52) (53) (54) (55) (56) (57) (58) (59) (60) (61) (62) (63) (64) (65) (66) (67) (68) (69) (70) (71) (72) (73) (74) (75) (76) (77) (78) (79) (80) (81) (82) (83) (84) (85) (86) (87) (88) (89) (90) (91) (92) (93) (94) (95) (96) (97) (98) ( 99 ) (100) (101) (102) (103) (104) (105) (106) (107) (108) (109) (110) (111) (112) (113) (114) (115) (116) (117) (118) (119) (120) (121) (122) (123) (124)