о 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, а так же на приличную
документацию освещающую этот вопрос отдельное спасибо тому, кто ссылку даст.
После выполнения вызванной по INT процедуры команда IRET восстанавливает содержимое всех этих регистров (в том числе переключаясь на прежний стек, если это нужно). При этом не имеет значения, была ли прерванная процедура 16-разрядной или 32-разрядной - все равно все регистры сохраняются в 32-разрядном виде.
ret и db66 ret в PM?
При этом команда 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-разрядного.