Переключение задач
Для переключения задач имеются следующие возможности:
- переключение по команде JMP;
- переключение по команде CALL;
- переключение по прерыванию.
В первом и втором случаях для переключения задачи используются обычные команды JMP и CALL, но в качестве операнда в этих командах указывается адрес сегмента TSS задачи, на которую необходимо переключиться.
Если произошло переключение с первой задачи на вторую при помощи команды JMP, то для возврата к выполнению первой задачи необходимо вновь использовать JMP, указав в качестве операнда адрес TSS первой задачи.
Команда CALL позволяет организовать вызов вложенных задач. Переключившись из первой задачи на вторую, программа может вновь вернуться к первой задаче, если она выполнит команду IRET. В этом случае по команде IRET произойдет обратное переключение задач. Адрес TSS для возврата команда IRET возьмёт из поля обратной связи Link текущего сегмента TSS, куда он был записан командой CALL при первом переключении задач.
Кроме того, при переключении задачи командой CALL в поле FLAGS сегмента TSS вызванной задачи устанавливается в 1 бит вложенной задачи NT. Команда JMP, если она использована для переключения задачи, сбрасывает бит NT. Формат регистра флагов для процессоров i80386 и i80486 описан в приложении. Регистр флагов FLAGS процессора i80286 - это младшее слово 32-разрядного регистра EFLAGS.
Аналогично тому, как можно вызвать подпрограмму через вентиль вызова, для вызова задачи командой CALL можно использовать вентиль задачи. Формат вентиля задачи представлен на рис. 16.
Рис. 16. Вентиль задачи.
Вентили задач, вызываемых по команде CALL, могут располагаться в таблицах GDT или LDT.
Обратите внимание на одно существенное различие между вызовом подпрограммы и вызовом задачи. После возврата из подпрограммы при её повторном вызове мы войдём в процедуру в начальной точке входа. В аналогичном случае при возврате из задачи и её повторном вызове управление будет передано команде, находящейся сразу за командой IRET.
Это происходит потому, что при переключении задачи в сегменте TSS записывается содержимое регистров CS:IP на момент переключения задачи. Если задача была вызвана при помощи команды CALL и возврат (обратное переключение) было выполнено по команде IRET, в TSS записывается адрес CS:IP, указывающий на следующую после IRET команду. Вы можете поместить там команду безусловного перехода JMP на начало задачи и таким образом зациклить задачу. После этого вызов задачи станет похож на вызов подпрограммы.
Существует ещё одна очень интересная возможность для переключения задач - переключение задач по прерыванию.
Эту возможность можно легко реализовать, если поместить вентиль задачи в дескрипторную таблицу прерываний IDT. Например, можно сделать отдельные задачи для обработки исключений или аппаратных прерываний. В последнем случае обработчикам аппаратных прерываний не нужно использовать стек прикладных задач, так как они будут иметь свой собственный стек.