XD-3D_HD_BLC
Панель навигации echo "/n"; ?> |
|
|
|
 |
XD-3D_HD_BLC
XD-3D_HD_BLC
Наши опросы echo "/n"; ?> |
|
|
|
 |
|
 | РЕКЛАМА |  |
|
|
|
 |
|
 |
 |
|
 |
|
вызовы подпрограмм
практически в любой программе, независимо
от ее содержания, встречаются участки,
которые требуется выполнять (возможно, с
небольшими изменениями) несколько раз по
ходу программы. такие повторяющиеся
участки целесообразно выделить из общей
программы, оформить в виде подпрограмм и
обращаться к ним каждый раз, когда в
основной программе возникает
необходимость их выполнения.
подпрограмма, в зависимости от выполняемых
ею функций, может требовать передачи из
вызывающей программы определенных данных (называемых
аргументами, или параметрами), возвращать в
вызывающую программу результаты
вычислений или обходиться и без того, и без
другого.
подпрограмма может быть оформлена в виде
процедуры, и тогда имя этой процедуры будет
служить точкой входа в подпрограмму:
drawline proc ;подпрограмма-процедура
. . . ;тело подпрограммы
ret ;команда возврата в вызывающую программу
drawline endp
с таким же успехом можно обойтись без
процедуры, просто пометив первую строку
программы некоторой меткой:
drawline: ;подпрограмма, начинающаяся с метки
. . . ;тело подпрограммы
ret ;команда возврата в вызывающую программу
. . . ;продолжение основной программы или
;другие подпрограммы
в любом случае вызов подпрограммы
осуществляется командой call. подпрограмма
должна завершаться командой ret, служащей
для возврата управления в ту точку, откуда
подпрограмма была вызвана.
вопросы использования подпрограмм,
передачи в них параметров и возвращения
результата будут рассмотрены в следующей
главе. здесь мы остановимся только на таких
принципиальных архитектурных вопросах, как
механизм выполнения и возможности команд
call и ret. при этом надо иметь в виду, что
синтаксические особенности и
закономерности использования команд call и jmp
во многом совпадают, и значительная часть
пояснений к командам перехода справедлива
и для команд вызова.
команда вызова подпрограммы call может
использоваться в 4 разновидностях. вызов
может быть:
прямым ближним (в пределах текущего
сегмента команд);
прямым дальним (в другой сегмент команд);
косвенным ближним (в пределах текущего
сегмента команд через ячейку с адресом
перехода);
косвенным дальним (в другой сегмент команд
через ячейку с адресом
перехода).
рассмотрим последовательно перечисленные
варианты.
прямой ближний вызов. как и в случае прямого
ближнего перехода, в команде прямого вызова
в явной форме указывается адрес (смещение)
точки входа в подпрограмму; в качестве
этого адреса можно использовать как имя
процедуры, так и имя метки, характеризующей
точку входа в подпрограмму. в код команды,
кроме кода операции e8h, входит смещение к
вызываемой подпрограмме. в приведенном
ниже примере подпрограмма оформлена в виде
процедуры.
code segment
main proc ;основная программа
…
call sub ;код е8 dddd
…
main endp
sub proc near ;подпрограмма
…
ret ;код сз
sub endp
code ends
процедура-программа находится в том же
сегменте команд, что и вызывающая программа.
в коде команды dddd обозначает смещение в
сегменте команд к точке входа в
подпрограмму. при выполнении команды call
процессор помещает адрес возврата (содержимое
регистра ip) в стек выполняемой программы (рис.
2.16), после чего к текущему содержимому ip
прибавляет dddd. в результате в ip оказывается
адрес подпрограммы. команда ret, которой
заканчивается подпрограмма, выполняет
обратную процедуру - извлекает из стека
адрес возврата и заносит его в ip.

рис. 2.16. участие стека в механизме вызова
ближней подпрограммы.
участие стека в механизме вызова
подпрограммы и возврата из нее является
решающим. поскольку в стеке хранится адрес
возврата, подпрограмма, сама используя стек,
например, для хранения промежуточных
результатов, обязана к моменту выполнения
команды ret вернуть стек в исходное
состояние. команда ret, естественно, никак не
анализирует состояние или содержимое стека.
она просто снимает со стека верхнее слово,
считая его адресом возврата, и загружает
это слово в указатель команд ip. если к
моменту выполнения команды ret указатель
стека окажется смещенным в ту или иную
сторону, команда ret по-прежнему будет
рассматривать верхнее слово стека, как
адрес возврата, и передаст по нему
управление, что неминуемо приведет к краху
системы.
прямой дальний вызов. этот вызов позволяет
обратиться к подпрограмме из другого
сегмента. в код команды, кроме кода операции
9ah, входит полный адрес (сегмент плюс
смещение) вызываемой подпрограммы. обычно в
исходном тексте программы с помощью
описателя far ptr указывается, что вызов
является дальним, хотя, если транслятор
настроен на трансляцию в два прохода, этот
описатель не обязателен. структура
программного комплекса, содержащая дальний
вызов подпрограммы, может выглядеть
следующим образом:
codel segment
assume cs:codel
main proc ;основная программа
call far ptr subr ; код 9а dddd ssss
…
main endp
codel ends
code2 segment
assume cs:code2
subr proc far ;объявляем подпрограмму дальней
…
ret ;код св - дальний возврат
subr endp
code2 ends
процедура-подпрограмма находится в
другом сегменте команд той же программы. в
коде команды dddd обозначает относительный
адрес точки входа в подпрограмму в ее
сегменте команд, a ssss - се сегментный адрес.
при выполнении команды call процессор
помещает в стек сначала сегментный адрес
вызывающей программы, а затем
относительный адрес возврата (рис. 2.17).
далее в сегментный регистр cs заносится 5555 (у
нас это значение code2), а в ip - dddd (у нас это
значение subr). поскольку процедура-подпрограмма
атрибутом far объявлена дальней, команда ret
имеет код, отличный от кода аналогичной
команды ближней процедуры и выполняется по-другому:
из стека извлекаются два верхних слова и
переносятся в ip и cs, чем и осуществляется
возврат в вызывающую программу,
находящуюся в другом сегменте команд. в
языке ассемблера существует и явное
мнемоническое обозначение команды
дальнего возврата - retf.

рис. 2.17. участие стека в механизме вызова
дальней подпрограммы.
косвенный ближний вызов. адрес
подпрограммы содержится либо в ячейке
памяти, либо в регистре. это позволяет, как и
в случае косвенного ближнего перехода,
модифицировать адрес вызова, а также
осуществлять вызов не с помощью метки, а по
известному абсолютному адресу. структура
программы с косвенным вызовом подпрограммы
может выглядеть следующим образом:
code segment
main proc ;основная программа
…
call ds:subadr ;код ff 16 dddd
main endp
subr proc near ;подпрограмма
…
ret ;код сз
subr endp
code ends
data segment
…
subadr dw subr ;яейка с адресом подпрограммы
data ends
процедура-программа с атрибутом near
находится в том же сегменте, что и
вызывающая программа, а ее относительный
адрес в ячейке subadr в сегменте данных. в коде
команды dddd обозначает относительный адрес
слова subadr в сегменте данных. второй байт
кода команды (16h в данном примере) зависит от
способа адресации. косвенный вызов
позволяет использовать разнообразные
способы адресации подпрограммы:
call bx ; в вх адрес подпрограммы
call[bx] ; в вх адрес ячейки с адресом
подпрограммы
call[bx][si] ;в вх адрес таблицы адресов
подпрограмм,
;в si индекс в этой таблице.
tbl[si] ;tbl - адрес таблицы адресов подпрограмм,
;в si индекс в этой таблице
косвенный дальний вызов. отличается от
косвенного ближнего вызова лишь тем, что
подпрограмма находится в другом сегменте, а
в ячейке памяти содержится полный адрес
подпрограммы, включающий сегмент и
смещение.
codel segment
main proc ;основная программа
call dword ptr subadr ;код ff ie dddd
…
main endp
codel ends
code2 segment
subr proc far ;подпрограмма
…
ret ;код св
subr endp
code2 ends
data segment
…
subadr dd subr ;двухсловная ячейка с
;адресом подпрограммы
data ends
процедура-подпрограмма с атрибутом far
находится в другом сегменте команд той же
программы, а ее полный двухсловный адрес - в
ячейке subadr в сегменте данных. второй байт
кода команды (ie в данном примере) зависит от
способа адресации. косвенный дальний вызов,
как и косвенный ближний, позволяет
использовать различные способы адресации.
| |  | |  |
|
XD-3D_HD_BLC
XD-3D_HD_BLC
|
Мы обращаемся к тем, кому наш сайт не безразличен, к тем, кому он уже помог. Сделайте доброе дело и помогите нам в развитии нашего сайта. Просто нажмите на изображении кошелька и следуйте инструкциям.
Огромное спасибо за поддержку.
|
|
|
 |
XD-3D_HD_BLC
|