Операционная система, как однозадачная, так и многозадачная, должна предоставлять задачам средства вызова подпрограмм операционной системы, библиотечных подпрограмм, а также иметь средства для запуска задач, а при многозадачной работе средства быстрого переключения с задачи на задачу. Вызов подпрограммы отличается от запуска задачи тем, что в первом случае адресное пространство остается тем же (таблица LDT остается прежней), а при вызове задачи адресное пространство полностью меняется.
Вызов подпрограмм без смены кодового сегмента в защищенном режиме процессора i386 производится аналогично вызову в реальном режиме с помощью команд JMP и CALL.
Для вызова подпрограммы, код которой находится в другом сегменте (который может принадлежать библиотеке, другой задаче или операционной системе), процессор i386 предоставляет 2 варианта вызова, причем оба используют защиту с помощью прав доступа.
Первый способ состоит в непосредственном указании в поле команды JMP или CALL селектора сегмента, содержащего код вызываемой подпрограммы, а также смещение в этом сегменте адреса начала подпрограммы.
Рис. 2.25. Непосредственный вызов подпрограммы
Схема такого вызова приведена на рисунке 2.25. Здесь и далее показан только этап получения линейного адреса в виртуальном пространстве, а следующий этап (подразумевается, что механизм поддержки страниц включен) преобразования этого адреса в номер физической страницы опущен, так как он не содержит ничего специфического по сравнению с доступом к сегменту данных, рассмотренному выше. Разрешение вызова происходит в зависимости от значения поля C в дескрипторе сегмента вызываемого кода. При C=0 вызываемый сегмент не считается подчиненным, и вызов разрешается, только если уровень прав вызывающего кода не меньше уровня прав вызываемого сегмента. При C=1 вызываемый сегмент считается подчиненным и допускает вызов из кода с любым уровнем прав доступа, но при выполнении подпрограмма наделяется уровнем прав вызвавшего кода.
Рис. 2.26. Формат дескриптора шлюза вызова подпрограммы