void xxxCall (DWORD Service);
void xxxJmp (DWORD Service);
Service
— код сервисной функции. Старшие 16 разрядов представляют собой идентификатор VxD, младшие 15 разрядов — номер сервисной функции.
Служит для обращения к сервисным функциям VMM и других VxD. Код функции одновременно определяет и VxD, к которому происходит обращение, и саму функцию этого VxD, так что конструкции VMMxxx и VxDxxx
равнозначны. Константы для кодов функций определены во включаемых файлах соответствующих VxD; имена констант функций VxD, отличных от VMM, имеют уточняющие префиксы, например VPICD_Get_Version — запрос номера версии VPICD, драйвера виртуального контроллера прерываний.
Сервисные функции доступны только в драйверах, имеющих идентификаторы. К драйверам без идентификаторов «честный» доступ возможен только со стороны приложений. Со стороны других VxD он возможен лишь путем непосредственного поиска данного VxD в системном списке с последующим прямым доступом к таблице его сервисных функций.
Параметры для сервисной функции, как правило, передаются в регистрах; результаты возвращаются в регистрах и флагах процессора. Некоторые функции рассчитаны на вызов в стиле языков C, с помещением параметров в стек и возвратом результата в EAX. Имена функций, оформленных в стиле C, начинаются со знака подчеркивания (_).
Оба вызова оформляются в виде команды прерывания int 0x20, следом за которой размещается код функции. При первой отработке вызова VMM заменяет эту конструкцию на команду far call/jmp в соответствующий шлюз, что дает экономию времени при последующих вызовах. По этой причине конструкцию Int 20, если она не опознается отладчиком как VMMxxx/VxDxxx, нельзя проходить командой типа Step Over, так как стоп-точка будет установлена отладчиком сразу за командой Int и при этом будет испорчен расположенный за нею код функции. Отладчик SoftICE
корректно опознает эти конструкции.
Различие вызовов Call и Jmp
состоит в том, что вызов Call запоминает адрес возврата в стеке, а Jmp — нет. Методом Jmp
вызываются «фатальные» функции, не требующие возврата, а также функции, после которых нужен возврат сразу к вызвавшей функции, без восстановления регистров и других завершающих действий. Без хорошего понимания механизма работы вызова Jmp
лучше ограничиться использованием вызова Call.