Передача параметров процедуре




Лабораторная работа № 5

Подпрограммы. Передача параметров.

Цель работы

Целью работы является изучение использования подпрограмм и способов передачи параметров.

Введение

Механизм вызова подпрограмм и возврата в точку вызова заложен в систему команд любого процессора. Не оказалась исключением и линейка процессоров Intel. Этот механизм реализуется с использованием команд CALL и RET. Особенности их применения обусловлены необходимостью выполнять вызовы и возвраты не только внутри сегмента, но и между сегментами.

Для облегчения описания программ и подпрограмм в Ассемблерах предусмотрены специальные средства. В ассемблерах MASM, TASM и др. таким инструментом являются процедуры, для описания которых существуют директивы PROC и ENDP.

При передаче управления подпрограмме и последующем возврате управления вызывающей программе необходимо выполнять т. н. соглашения о связях, которые оговаривают, в частности:

- необходимость сохранения используемых подпрограммой регистров

- способ передачи параметров подпрограмме

Дополнительная информация должна учитываться, если модули, написанные на ассемблере, вызываются из модулей, написанных на языках высокого уровня, например, PASCAL, C, C++ и др.

Команды CALL и RET

Команды CALL и RET являются командами передачи управления, по своему действию похожие на команду безусловного перехода JMP т.к. они тоже изменяют естественный порядок выборки и исполнения команд, передавая управление в другую точку памяти. Главным и единственным отличием команды CALL от JMP состоит в том, что перед изменением регистров, содержащих указатель на следующую команду, их содержимое – адрес возврата – сохраняется в стеке, и лишь после этого выполняется переход на указанный адрес. Действие команды RET состоит в том, что она восстанавливает из стека содержимое регистров, указывающих на адрес следующей команды, выполняя возврат в точку вызова – на команду, следующую за соответствующей командой CALL.

Полный указатель на следующую исполняемую команду содержится в паре регистров CS:IP (CS:EIP). Регистр CS содержит указатель на сегмент, а регистр IP содержит значение смещения внутри сегмента. В 16-битной модели памяти если для сохранения информации о полном адресе в стек заносятся два 16-разрядных слова (содержимое CS и IP), то обеспечивается возможность последующего возврата из другого сегмента. Так «работает» команда CALL при межсегментном вызове и называется поэтому «дальним вызовом» (call far). Если вызываемая процедура находится в том же сегменте, что и вызывающая программа, то значение регистра CS не изменяется, значит, запоминать его нет необходимости, и в стек заносится только одно слово – текущее значение регистра IP. Такой внутрисегментный вызов называют «ближним вызовом» (call near). Очевидно, что при возврате, который реализует команда RET, должно восстанавливаться из стека ровно столько же слов, сколько было сохранено при вызове, т.е. тип возврата – «ближний» или «дальний» – должен строго соответствовать типу своего вызова. Таким образом, существуют возвраты ret far и ret near.

Процедуры

Если команда вызова подпрограммы и команда возврата из этой полпрограммы имеют разное типы (far и near или наоборот), то после выполнения команды возврата из стека выталкивается неправильное количество слов, а в случае ret far в CS загружается неопределенная информация. Все это приводит к краху программы и прекращению ее выполнения операционной системой. Чтобы избежать подобных ошибок, а также для получения дополнительных удобств при программировании, следует использовать описание подпрограмм, как процедур.

Для описания процедуры используются директивы PROC и ENDP. При открытии процедуры указывается ее имя и тип. Тип указывать не обязательно, если это near, т.к. тип near принят по умолчанию.

Пример:

abc proc far; открытие процедуры дальнего типа

; тело процедуры

ret; команда возврата

endp; закрытие процедуры

Следует отметить, что в приведенном примере использование команды возврата в качестве последней в теле процедуры носит условный характер. На самом деле обязательным является условие, чтобы возврат был последней исполняемой командой в процедуре, а не последней по расположению. В теле процедуры, в зависимости от логики работы, может быть несколько команд возврата.

Пример:

prog1 proc; открытие процедуры ближнего типа

push ax; сохранение регистров

push dx;

...;

jnz m1;

pop dx; восстановление регистров

pop ax;

ret; команда возврата

m1:;

...;

pop dx; восстановление регистров

pop ax;

ret; команда возврата

endp; закрытие процедуры

Передача параметров процедуре

При вызове процедуры в большинстве случаев ей передаются параметры из вызывающей программы. Параметры – это данные: байты, слова, строки, массивы или адреса байтов, слов, строк, массивов. Передача параметров по значению означает передачу самих данных, передача по ссылке означает передачу адресов. В обоих случаях возможна передача параметров через регистры, через общую память (по именам) или через стек.

Передача через регистр не требует комментариев, однако, следует отметить принятые неписаные правила: один параметр по значению передается через аккумулятор: байт – через AL, слово – через AX, двойное слово – через EAX (для 32-разрядной модели) или через DX,AX (для 16-разрядной модели). Передача нескольких параметров через регистры – не самое лучшее решение.

Передача параметров через общую память (по имени) реализуется очень просто, если вызывающая и вызываемая процедуры расположены в одном модуле. Однако, в этом случае процедуры перестают быть универсальными, т. к. связаны общими именами.

 
 

Передача параметров через стек – наиболее универсальный метод.

Вызывающая программа заталкивает аргументы в стек и делает вызов процедуры:

push x1; первый аргумент

push x2; второй аргумент

call sub1; вызов подпрограммы

 
 

После такой последовательности команд в стеке оказываются два параметра и адрес возврата. Для ближнего вызова адрес возврата – это одно слово, представляющее собой адрес команды, следующей за командой call.

Получив управление, подпрограмма может получить доступ к аргументам через регистр BP (B ase P ointer), специально для этого введенный в состав процессора. Предварительно сохранив его старое значение в стеке, в него переписывают текущее значение указателя стека:

push bp; сохранение старого значения BP

 
 

mov bp,sp; установка указателя базы BP

Из схемы видно, что аргументы доступны по адресам [bp+4], [bp+6] и т.д.:

mov ax,[bp+6]; пересылка первого аргумента в аккумулятор

mov cx,[bp+4]; пересылка второго аргумента в регистр CX

В случае дальнего вызова смещения будут: [bp+6], [bp+8] и т.д., т.к. адрес возврата будет занимать два слова в стеке.



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2016-04-27 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: