Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

о RET в PM

Аноним
Помогите разобраться с условиями возврата,
когда ставить RET far, а когда db 66h RET FAR.
Есть прога в 16/ и 32 ,битных кодовых сегментах, CPL разное. Ставлю вектор прерывания на int 1
- для дебайгера, он в 16 битном коде(так должен), CPL=0.
Он работает и возвращается по db 66 IREТ.
Вопрос: cколько параметров мне нужно выталкивать из стека в обработчике командой RET (IRET)? Т.е. как мне узнать, 32 битный или 16 битный сегмент вызвал этот INT 1, не лазя за описанием этого сегмента в GDT или LDT? (код ошибки уже учтен)
За ссылку на DEBUGGER, работающий в PM с нулевым кольцом защиты под DOS, а так же на приличную
документацию освещающую этот вопрос отдельное спасибо тому, кто ссылку даст.
461
05 февраля 2002 года
gerard
102 / / 20.12.1999
Вообще-то, никакой проблемы тут нет. Дело в том, что в PM при обработке прерывания ВСЕГДА используются 32-разрядные адреса. Когда возникает какое-либо прерывание, в стеке сохраняется содержимое следующих регистров: SS, ESP, EFLAGS, CS, EIP (первые два сохраняются, если прерванная процедура и вызванная имеют разный уровень привилегий - в этом случае происходит переключение стека).
После выполнения вызванной по INT процедуры команда IRET восстанавливает содержимое всех этих регистров (в том числе переключаясь на прежний стек, если это нужно). При этом не имеет значения, была ли прерванная процедура 16-разрядной или 32-разрядной - все равно все регистры сохраняются в 32-разрядном виде.
Аноним
А почему же есть большая разница между
ret и db66 ret в PM?
461
26 февраля 2002 года
gerard
102 / / 20.12.1999
А для возврата из обычной процедуры, вызванной командой CALL, разница есть. Если процедура выполнялась в 16-разрядном режиме, то команда RET восстановит из стека регистр IP (2 байта), а если в 32-разрядном - то регистр EIP (4 байта). Команда RETF (или RET FAR) восстановит также и CS (то есть в сумме получается 4 или 6 байт соответственно).

При этом команда RET (RETF) не определяет, какой адрес (16- или 32-разрядный) был помещен в стек - за этим нужно следить самому. То есть, если сегмент основной программы и сегмент процедуры имеет одинаковую разрядность (16 или 32), то нужно ставить вызов CALL, а если разную - то CALL с префиксом 66h (он меняет используемый для текущего сегмента размер на противоположный).

Кстати, команда RET n (RETF n) тоже работает по-разному в 16- и 32-разрядном сегменте. В первом случае она дополнительно увеличивает SP на величину n, а во втором - на величину 2*n.

Например, вы используете 32-разрядную процедуру, в которую передается через стек 8 байт (4 слова) параметров. Тогда она должна завершать командой RET 4, а вызываться командой CALL из 32-разрядного сегмента и командой db 66h CALL - из 16-разрядного. Если же поставить db 66h перед RET, то нужно использовать ее в виде db 66h RET 8. Тогда процедура должна вызываться командой CALL из 16-разрядного сегмента и командой db 66h CALL - из 32-разрядного.

Знаете кого-то, кто может ответить? Поделитесь с ним ссылкой.

Ваш ответ

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог