"Ближние" формы команды RET выполняют передачу управления только в пределах текущего кодового сегмента, и следовательно, для них выполняется только контроль границ. Смещение для команды, следующей после команды вызова CALL, извлекается из стека и помещается в регистр EIP. Процессор контролирует, чтобы это смещение не превосходило границу текущего кодового сегмента.
"Дальняя" форма команды RET извлекает адрес возврата, помещенный в стек предыдущей командой CALL. В нормальных условиях указатель возврата всегда достоверен, поскольку он был сгенерирован командой CALL или INT. Тем не менее, процессор выполняет проверку привилегированности вследствие возможности того, что текущая процедура изменила указатель или не смогла правильно обработать стек. RPL селектора кодового сегмента, извлеченный из стека командой возврата, должен иметь уровень привилегированности вызывающей процедуры.
Возврат в другой сегмент может изменить уровни привилегированности, но только в сторону более низких уровней. Когда команда RET встречает сохраненное значение CS, RPL которого численно больше CPL (т.е. имеет более привилегированный уровень), происходит возврат через уровни привилегированности. Такого рода возврат выполняет следующие шаги:
Выполняются проверки, показанные в Таблице 6-2 и регистры CS, EIP, SS и ESP загружаются их предыдущими значениями, которые были сохранены в стеке.
Старое содержимое регистров SS и ESP (из вершины текущего стека) настраивается по размеру в байтах, заданному в команде RET. Результирующее значение ESP не проверяется на границу стекового сегмента. Если значение ESP выходит за эту границу, то этот факт не распознается процессором до следующей стековой операции. (Содержимое регистров SS и ESP для возвращаемой процедуры не сохраняются; обычно их значения те же, что и хранимые в TSS).
Проверяется содержимое сегментных регистров DS, ES, FS и GS. Если хоть один из этих регистров ссылается на сегмент, DPL которого меньше нового CPL (включая конформные кодовые сегменты), сегментный регистр загружается пустым селектором (Индекс=0, TI=0). Сама команда RET в таких случаях не сообщает об исключениях; однако любые последующие ссылки к памяти при помощи сегментного регистра, содержпщего пустой селектор, вызовут исключение общей защиты. Это не позволяет менее привилегированным кодам обращаться к более привилегированным сегментам посредством селекторов, оставленных в сегментных регистрах более привилегированной процедурой.
Таблица 6-2. Проверки при возврате между процедурами с разными уровнями привилегированности ------------------------------------------------------------------|Тип проверки | Тип особой ситуации | Код ошибки|------------------------------------------------------------------|Вершина стека должна быть ||в пределах границы сегмента ||стека Стек 0 || ||Адрес Вершины стека+7 должен быть ||в пределах границы сегмента ||стека Стек 0 || ||RPL кодового сегмента возврата ||должен превышать CPL Защита CS возврата|| ||Селектор кодового сегмента ||возврата не должен быть пустым Защита CS возврата|| ||Дескриптор кодового сегмента ||возврата должен быть в пределах ||границы таблицы дескрипторов Защита CS возврата|| ||Дескриптор сегмента возврата ||должен относиться к кодовому ||сегменту Защита CS возврата|| ||Присутствие кодового сегмента Сегмент не ||возврата присутствует CS возврата|| ||DPL не-конформного кодового ||сегмента возвратв должен быть ||равен RPL селектора кодового ||сегмента возврата, либо DPL ||конформного кодового сегмента ||возврата должен быть меньше ||или равен RPL селектора кодового ||сегмента возврата Защита CS возврата|| ||ESP+N+15* должно находиться ||в пределах границы сегмента ||стека Сбой в стеке CS возврата|| ||Селектор сегмента в ESP+N+12* ||не должен быть пустым Защита CS возврата|| ||Дескриптор сегмента в ESP+N+12* ||должен находиться в пределах ||границы таблицы дескрипторов Защита CS возврата|| ||Дескриптор стекового сегмента ||должен быть доступен для ||чтения/записи Защита CS возврата|| ||Должен присутствовать стековый ||сегмент Сбой в стеке CS возврата|| ||DPL старого стекового сегмента ||должен быть равен RPL старого ||кодового сегмента Защита CS возврата|| ||Селектор старого стекового ||сегмента должен иметь RPL, ||равный DPL старого стекового ||сегмента Защита CS сегмента|------------------------------------------------------------------ * N - это значение непосредственного операнда, заданного в команде RET.