
- •Регистровая адресация
- •Непосредственная адресация
- •Прямая адресация (па)
- •Косвенная регистровая адресация (кра).
- •Адресация с базированием (аб)
- •Адресация с индексированием (аи).
- •Адресация с базированием и индексированием (аби)
- •Использование стека
- •Организация подпрограмм
- •Команды вызова подпрограмм
- •Команды возврата из подпрограмм
- •Директива процедуры
- •Передача параметров в подпрограмму
Организация подпрограмм
Если некоторая последовательность команд должна выполняться в нескольких местах программы, то целесообразно выделить эту последовательность в подпрограмму.
На первый взгляд для перехода к выполнению подпрограммы можно воспользоваться командой безусловного перехода — ведь код подпрограммы начинается с определенного адреса, к этому адресу и нужно переходить (т.е. помещать его в IP или CS:IP). Но как затем вернуться в вызывающую программу? Ведь подпрограмма может вызываться из разных мест главной программы.
Для организации связи программы и подпрограммы служит пара команд: вызов (call) и возврат (ret — сокращение от return).
В вызывающей подпрограмму программе выполняется инструкция CALL, которая заносит адрес следующей инструкции в стек и загружает в регистр IP адрес соответствующей подпрограммы, осуществляя таким образом переход на подпрограмму. После этого подпрограмма выполняется, как любой другой код. В подпрограммах могут (часто это так и бывает) содержаться инструкции вызовов других подпрограмм. Фактически, должным образом построенные подпрограммы могут даже вызывать сами себя (это называется рекурсией).
Когда подпрограмма заканчивает работу, она вызывает инструкцию RET, которая извлекает из стека адрес, занесенный туда соответствующей инструкцией CALL, и заносит его в IP. Это приводит к тому, что вызывающая программа возобновит выполнение с инструкции, следующей за инструкции CALL.
Команды вызова подпрограмм
Команда вызова подпрограммы CALL передает управление с автоматическим сохранением адреса возврата в стеке. В поле операнда этой команды находится метка первой команды вызываемой подпрограммы.
При переходе к подпрограмме необходимо временно запомнить адрес команды, находящейся после команды CALL. Этот адрес называется адресом возврата. После того, как подпрограмма закончит свои действия, завершающая ее команда возврата RET передает управление по запомненному адресу возврата. Адрес возврата запоминается в стеке.
Вызовы могут быть внутрисегментными (тип NEAR) или межсегментными (тип FAR). В первом случае вызываемая подпрограмма находится в текущем сегменте кода, а во втором – в произвольном участке памяти.
Команды внутрисегментного перехода производят декремент SP на 2, включают в стек содержимое IP, а затем прибавляют к IP 16-битное смещение, которое интерпретируется как знаковое целое. Команды межсегментного перехода производят декремент SP на 2, включают в стек содержимое CS, снова производят декремент SP на 2, включают в стек содержимое IP, затем в IP загружается значение смещения, а в CS - сегментный адрес.
Формат команды:
CALL disp – непосредственный ближний вызов;
CALL mem/reg – косвенный ближний вызов;
CALL addr – непосредственный дальний вызов;
CALL mem – косвенный дальний вызов.
Команды возврата из подпрограмм
Каждая подпрограмма должна содержать минимум одну команду возврата RET, которая возвращает управление вызывающей программе. Такая передача управления осуществляется путем извлечения из стека адреса возврата, включенного в него командой вызова подпрограммы.
Команды внутрисегментного и межсегментного возврата имеют одну и ту же мнемонику RET. Тип команды, соответствующей этой мнемонике, определяется ассемблером автоматически.
Формат команды:
RET – однобайтный вариант,
RET data – трехбайтный вариант.
Однобайтная команда RET с кодом операции C3 реализует внутрисегментный возврат. Она передает слово из вершины стека в IP и увеличивает SP на 2. Синонимом данной команды является команда RETN.
Однобайтная команда RET с кодом операции CB осуществляет межсегментный возврат. Она передает слово из вершины стека в IP, увеличивает SP на 2, передает слово из вершины стека в CS и снова увеличивает SP на 2. Синонимом данной команды является команда RETF.
Трехбайтные варианты команд возврата осуществляют те же действия, что и однобайтные, а затем прибавляют содержащиеся в них данные к указателю стека. Эти команды предназначены для упрощения возврата из тех подпрограмм, параметры которых передаются в стеке. Прибавление к SP данных из RET эквивалентно удалению параметров из стека.
Для того, чтобы ассемблер правильно генерировал машинный код для команды RET, используется директива объявления процедуры.