The hunt for a faster syscall trap - о том, как в Windows/386 (версия, которая предшествовала Windows 3.0) переходили из V86-режима в защищённый (protected mode) при помощи ошибочной инструкции.
Faster Syscall Trap redux - о том, как OS/2 под 286-м процессором использовала ещё более извращённый трюк для возвращения из защищённого режима в реальный режим (real mode) - при помощи втройне ошибочной инструкции (triple fault)!
Я могу рассказать что-то похожее, но далеко не столь впечатляющее, в области CPU-трюков. Пробуя различные инструкции и режимы своего 386-го, году в 92-м или 93-м я обнаружил один интересный трюк (не сомневаюсь, что он был известен многим знатокам ассемблера в то время, но я его придумал сам и тем гордился).
Когда процессор 80386 работал в "реальном режиме", доступная для инструкций процессора память ограничивалась 64 килобайтами (16-битный режим); для того, чтобы использовать больше памяти, существовала система сегментных регистров и доступов через эти сегменты - система, как помнят все, кому приходилось иметь с ней дело, исключительно неудобная.
После перехода в "защищённый режим" CPU переходил к 32-битной адресации и всю память можно было видеть "напрямую". Сегментные регистры оставались (и есть в интеловских процессорах до сих пор), но, как правило, их конфигурируют так, что каждый сегмент (кода, данных, дополнительных данных итп.) указывает на всю протяжённость виртуальной памяти с нуля и до 4Gb, т.е. по сути дела сегменты не используют (есть определённые исключения из этой практики, но не буду сейчас на них останавливаться). С другой стороны, если вы обычном пользуетесь DOS-ом (а не какими-нибудь Линуксами, которые тогда были в зачаточном состоянии, или Windows 95, которого тогда просто не было), то переходить в защищённый режим довольно неудобно - DOS из его не вызвать, очень многие вещи поэтому приходится делать самому, все обычные программы и TSRы ("резидентные" утилиты, бегущие в DOSe и дополняющие его возможности) перестают работать итп. Программу, работающую с файлами, рисующую что-то итп., гораздо удобнее было писать в "реальном" режиме; но с другой стороны, это идиотское ограничение в 64k очень мешало.
У 80386 не было двух разных наборов инструкций для работы с 16-битными данными, регистрами и адресами (в "реальном" режиме или в режиме эмуляции V86) и для работы с 32-битными данными, регистрами и адресами. Все обычные инструкции - арифметические, инструкции обмены данными между регистрами и памятью, итд. итп. - существовали только в одном варианте, но их аргументы - адреса в памяти, или непосредственно числа - были 16- или 32-битными в зависимости от того, в каком режиме находился процессор. Имелась также префиксная инструкция размером в один байт, которая меняла "размерность" следующей за ней инструкции с 16 на 32 бита или наоборот. Например, если процессор находился в 32-битном режиме, то обычно все адреса или числа в инструкциях, которые он читал, должны были быть 32-битными, но если стоял этот префикс, они были 16-битными. И наоборот.
Казалось бы, можно было, работая в "реальном" режиме, использовать этот префикс, и вместе с ним - инструкции с 32-битными адресами, выходя за пределы сегмента размером в 64Kb. Но на практике это вызывает ошибку доступа к памяти, процессор не даёт выйти за пределы сегмента.
Трюк, который я придумал, состоял в том, чтобы перейти в защищённый режим, а потом в нём очень аккуратно выставить все регистры так, какими они "должны" быть в реальном режиме, и вернуться реальный режим путём сброса бита в контрольном регистре процессора (бита, который регулирует 16<-->32 битность процессора). Но при этом делается одно небольшое изменение: размеры этих сегментов я определял на 64Kb (какими они являются обычно в реальном режиме), а все 4Gb. Иными словами, этот трюк опирается на тот факт, что "внутри" процессора реальный режим является частным случаем защищённого: разница только в том, что 32-битность меняется на 16-битность, и все сегментные дескрипторы забиты определёнными дефолтными значениями. Путём перехода в защищённый режим, некоторых изменений сегментных дескрипторов с целью "освободить" сегменты от 64kb-ной защиты, и возвращение в реальный режим мы и получаем то, что хотели. Теперь процессор бежит в реальном режиме, но используя префикс адресации, можно работать со всей имеющейся памятью одновременно - а это исключительно удобно.
Я не использовал этот трюк ни для чего серьёзного, кроме прототипа одной игры, которую писал (но всё осталось на уровне прототипа) и нескольких тестовых программ. Но всё равно приятно было.
P.S. Погуглил немного; судя по всему обычное название для этого трюка - "flat real mode". Если поискать Гуглом эту фразу, можно найти несколько более подробных объяснений с примерами.