В языке ассемблера есть несколько средств, решающих проблему дублирования участков программного кода. К ним относятся: механизм процедур; макроассемблер; механизм прерываний.
Процедура представляет собой группу команд для решения конкретной подзадачи и обладает средствами получения управления из точки вызова задачи более высокого уровня и возврата управления в эту точку.
В простейшем случае программа может состоять из одной процедуры. Другими словами, процедуру можно определить как правильным образом оформленную совокупность команд, которая, будучи однократно описана, при необходимости может быть вызвана в любом месте программы. Процедура, часто называемая также подпрограммой. Вызов процедуры осуществляется с помощью команды CALL <имя процедуры>. При вызове процедуры адрес точки возврата запоминается в стеке (как будет описано при описании команд). Возврат из процедуры происходит с помощью команды RET (или RETF), по которой из стека достается и загружается в IP сохраненный в стеке адрес точки возврата.
|
|
Для описания последовательности команд в виде процедуры в языке ассемблера используются две директивы: PROC и ENDP.
В заголовке процедуры (директиве PROC) обязательным является только задание имени процедуры. Среди большого количества операндов директивы PROC следует особо выделить [расстояние].
Этот атрибут может принимать значения near или far и характеризует возможность обращения к процедуре из другого сегмента кода. По умолчанию атрибут [расстояние] принимает значение near.
Процедура может размещаться в любом месте программы, но так, чтобы на нее случайным образом не попало управление. Если процедуру просто вставить в общий поток команд, то микропроцессор будет воспринимать команды процедуры как часть этого потока, и соответственно будет осуществлять выполнение команд процедуры.
Схема команды: call цель
Назначение:
передача управления близкой или дальней процедуре с запоминанием в стеке адреса точки возврата;
переключение задач. Алгоритм работы определяется типом операнда: метка ближняя — в стек заносится содержимое указателя команд eip/ip и в этот же регистр загружается новое значение адреса, соответствующее метке;
метка дальняя — в стек заносится содержимое указателя команд eip/ip и cs. Затем в эти же регистры загружаются новые значения адресов, соответствующие дальней метке;
г16, 32 или ml6, 32 — определяют регистр или ячейку памяти, содержащие смещения в текущем сегменте команд, куда передается управление. При передаче управления в стек заносится содержимое указателя команд eip/ip;
указатель на память — определяет ячейку памяти, содержащую 4 или 6- байтный указатель на вызываемую процедуру. Структура такого указателя 2+2 или 2+4 байта Интерпретация такого указателя зависит от режима работы микропроцессора:
|
|
в реальном режиме — в зависимости от размера адреса (use 16 или use32) первые два байта трактуются как сегментный адрес, вторые два/четыре байта, как смещение целевой метки передачи управления. В стеке запоминается содержимое регистров cs и eip/ip;
в защищенном режиме — интерпретация цели передачи управления зависит от значения байта AR дескриптора, определяемого селекторной частью указателя.
Целью здесь являются дальний вызов процедуры без изменения уровня привилегий, дальний вызов процедуры с изменением уровня привилегий или переключение задачи. Состояние флагов после выполнения команды (кроме переключения задачи): выполнение команды не влияет на флаги
При переключении задачи значения флажков изменяются в соответствии с информацией о регистре eflags в сегменте состояния TSS задачи, на которую производится переключение. Применение:
Как видно из описания алгоритма, команда call позволяет организовать гибкую и многовариантную передачу управления на подпрограмму с сохранением адреса точки возврата. См. также команду ret RET/RETF
(RETurn/RETum Far from procedure) Возврат ближний (дальний) из процедуры
Схема команды, ret ret число
Назначение: возврат управления из процедуры вызывающей программе. Алгоритм работы: Работа команды зависит от типа процедуры:
для процедур ближнего типа — восстановить из стека содержимое eip/ip; для процедур дальнего типа — последовательно восстановить из стека содержимое eip/ip и сегментного регистра cs
если команда ret имеет операнд, то увеличить содержимое esp/sp на величину операнда число; при этом учитывается атрибут режима адресации — use 16 или use32:
если use 16, то в sp = (sp +число), то есть указатель стека сдвигается на число байт, равное значению числа;
если use32, то sp=(sp+2*число), то есть указатель стека сдвигается на число слов, равное значению числа.
Состояние флагов после выполнения команды: выполнение команды не влияет на флаги
Применение:
Команду ret необходимо применять для возврата управления вызывающей программе из процедуры, управление которой было передано по команде call. На самом деле микропроцессор имеет три варианта команды возврата ret - это ret, ее синоним retn, а также команда retf. Они отличаются типами процедур, в которых используются. Команды ret и retn служат для возврата из процедур ближнего типа. Команда retf — команда возврата для процедур дальнего типа. Какая конкретно команда будет использоваться, определяется компилятором; программисту лучше использовать команду ret и доверить транслятору самому сгенерировать ее ближний или дальний вариант. Количество команд ret в процедуре должно соответствовать количеству точек выхода из нее.
В процедуру (и из процедуры) параметры могут передаваться.
- через общие переменные. Данный способ не требует особых комментариев - перед вызовом процедуры в переменную заносится необходимое значение данных, а затем в процедуре происходит обращение к данной переменной;
- через регистры. Этот способ передачи управления отличается от предыдущего способа только тем, что через регистр можно организовать косвенную передачу параметра, а не только данных;
- через стек. В этом случае перед вызовом процедуры в стек заносят необходимое значение переменной, а в процедуре идет обращение внутрь стека. Важно не трогать указатель
стека SP для того, что бы нормально выйти из процедуры, так как в вершине стека хранится адрес точки возврата. Поэтому для обращения внутрь стека используется регистр ВР.
Основная литература: 2[236-246],9[152-168],7[135-139]
Дополнительная литература:14[75-79]
|
|
Контрольные вопросы:
1. Что такое процедура (подпрограмма) в ассемблере? Как оформляется процедура?
2. Как осуществляется запоминание адреса точки возврата в основную программу?
3. Как происходит возврат из процедуры в основную программу?
4. Назовите команду вызова процедуры?
5. Назовите команду возврата из процедуры?
6. Каким образом можно передать параметры в процедуру?
7. Каким образом можно передать параметры из процедуры в основную программу?
8. Как осуществить передачу параметров через стек.