Поскольку управление стеком различается для 16-разрядных и 32-разрядных команд CALL и RET, размер операнда в команде RET должен соответствовать размеру операнда в команде CALL. (Смотри Рисунок 24-1). 16-разрядная команда CALL заносит в стек содержимое 16-разрядного регистра IP и (для вызовов между разными уровнями привилегированности) 16-разрядного регистра SP. Соответствующая команда RET также должна использовать 16-разрядный операнд для выборки этого 16-разрядного значения из стека в 16-разрядный регистр. 32-разрядная команда CALL заносит в стек содержимое 32-разрядного регистра EIP и (для внутриуровневых вызовов) 32-разрядного регистра ЕSP. Соответствующая команда RET также должна использовать 32-разрядный операнд для выборки этого 16-разрядного значения из стека в 32-разрядный регистр. Если две части командной пары CALL /RET имеют операнды различной длины, взаимодействие со стеком будет некорректным, и значения указателя команды и указателя стека не будут корректно восстановлены.
Когда команда CALL и соответствующая ей команда RET находятся в сегментах, имеющих одинаковые значения D-бита (т.е. обе по умолчанию 32-разрядные или обе по умолчанию 16-разрядные), могут быть использованы установки по умолчанию. Если же команда CALL и соответствующая ей команда RET находятся в сегментах имеющих различные значения D-бита , должны быть использованы префиксы размера операнда.
Существует три способа выполнения 32-разрядного вызова 16-разрядной процедурой:
Использовать 16-разрядный вызов 32-разрядной интерфейсной процедуры, которая осуществит 32-разрядный вызов из заданного места.
Осуществить вызов через 32-разрядный шлюз вызова.
Изменить 16-разрядную процедуру, вставив перед вызовом префикс размер операнда, превращающий этот вызов в 32-разрядный.
Точно так же существует и три способа выполнения 16-разрядного вызова 32-разрядной процедурой:
Использовать 32-разрядный вызов 32-разрядной интерфейсной процедуры, которая осуществит 16-разрядный вызов из заданного места.
Осуществить вызов через 16-разрядный шлюз вызова.
Изменить 32-разрядную процедуру, вставив перед вызовом префикс размера операнда, превращающий этот вызов в 16-разрядный. (Необходимо следить, чтобы возвращаемое смещение не превосходило 0FFFFH).
Программист может использовать любой из приведенных выше методов выполнения команды CALL в 16-разрядном сегменте, подобрав ей соответствующую команду RET в 32-разрядном сегменте, или выполнить команду CALL в 32-разрядном сегменте, подобрав ей соответствующую команду RET в 16-разрядном сегменте.