Форум программистов, компьютерный форум, киберфорум
_lunar_
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  

Стек вызовов Windows API

Запись от _lunar_ размещена 11.04.2022 в 14:59
Показов 2553 Комментарии 0
Метки c, c++, winapi

В этой записи я постараюсь простым понятным языком объяснить что такое API в целом, а также его разновидности в зависимости от того, где это API исполняется.

Сперва, предлагаю внимательно посмотреть на скриншот и запомнить последовательность вызовов
(не стал рисовать свои скриншоты, т.к. этот в полной мере описывает весь процесс)
Нажмите на изображение для увеличения
Название: 1.png
Просмотров: 550
Размер:	57.6 Кб
ID:	7441

Итак, после того, как исходный код был скомпилирован, появляется пользовательское приложение (файл с расширением *.exe).
EXE файл это исполняемый файл со строго типизированной структурой заголовка Portable Executable (PE).
Формат PE достаточно объемный, и поэтому кажется сложным. Но Microsoft любезно предоставляет спецификацию этого формата PE Format, так что с освоением проблем не должно возникнуть.
Такая структурированность требуется для того, чтобы загрузчик Windows смог проецировать таблицы с кодом, заложенные в EXE файле, в виртуальное адресное пространство, для дальнейшего его исполнения на процессоре (инструкция за инструкцией).

Я сейчас не буду подробно останавливаться на каждой таблице, но нужно запомнить вот что:
у EXE файлов всегда есть таблица импорта адресов - Import Address Table (IAT) (за исключением случаев, когда код написан без среды выполнения C Runtime (CRT)).

Вернёмся на шаг назад - к исходному коду.
Когда программист пишет код будущего пользовательского приложения, он использует заготовленные файлы хидеров (Header), в которых определены различные константы, прототипы функций и многое другое.
Хидер это просто текст и не более.
Ещё программист использует библиотеки (*.lib), чтобы связать (слинковать) прототип функции из хидера с реальной функций в одной из системных библиотек DLL.
Именно эта связь формирует таблицу импорта адресов (IAT) в заголовке PE будущего EXE файла.

Снова вернёмся к скриншоту, на котором для примера выбрана функция WriteFile и весь её стек вызовов.
И вот тут уже можно начинать задать вопрос - что же такое Application Programming Interface (API)?

Начнем с пользовательского окружения - то, что доступно непосредственно пользователю: Windows API (WinAPI).
WinAPI это документированное API, т.е. к прототипам его функций есть описание и спецификации.
WinAPI представляет собой массивный набор функций, распределенный по нескольким системным библиотекам DLL.
Основные системные библиотеки пользовательского окружения: kernelbase.dll (до Windows 8 это была kernel32.dll и теперь она служит лишь стабом для совместимости), user32.dll, gdi32.dll, advapi32.dll, ntmarta.dll, shell32.dll и др.
В них собрано огромное количество функций, которые и формируют WinAPI.

Когда программист в коде использует функцию WriteFile, он вызывает её API из соответствующей системной библиотеки (в данном случае kernel32.dll).
По сути API это ничто иное как исполняемый код в самой библиотеки DLL.
Там выполняются различные internal функции (не экспортируемые функции), вычисления, заполнение переменных, переданных программистом через аргументы функции WriteFile.
Формируется так называемый пользовательский контекст - массив данных, который передаётся ядру ОС через ссылку на стек (шлюз)
Assembler
1
2
3
4
5
proc near
    mov edx, esp
    syscall ; mov edx, 7FFE0300 // SharedUserData!SystemCallStub (в 7FFE0300 находится адрес KiFastSystemCall)
    retn
endp
Конечным результатом внутреннего исполнения функции WriteFile в библиотеке kernel32.dll будет вызов функции NtWriteFile с тем самым пользовательским контекстом.

Есть ещё несколько библиотек пользовательского окружения, таких как ntdll.dll и win32u.dll, функции которых доступны из UserMode.
Набор их функций формирует так называемое NativeAPI.
NativeAPI это недокументированное API, и разбор прототипов его функций осуществляется энтузиастами в ручном режиме с помощью отладчиков и дизассемблеров.
Главная задача этих функций - передать пользовательский контекст в ядро ОС.
Делается это переключением (или точнее системным прерыванием) процессора в защищенный режим (ProtectedMode).
В современных ОС и процессорах для этого используются инструкции SYSCALL или SYSENTER (внутри KiFastSystemCall) (в старых ОС это системное прерывание называлось int 2e (внутри KiIntSystemCall))
Нажмите на изображение для увеличения
Название: 2.png
Просмотров: 473
Размер:	64.8 Кб
ID:	7442
Возврат контекста из ядра ОС в пользовательский режим осуществляется инструкциями SYSRET или SYSEXIT (внутри KiFastSystemCallRet).

После того, как процессор перешёл в защищенный режим (ProtectedMode), переданный пользовательский контекст начинает обрабатываться в ядре ОС - ntoskrnl.exe
Для этого используется процедура ZwWriteFile (не путайте с функций NtWriteFile из библиотеки ntdll.dll).
Код API, который исполняется в ядре ОС называется KernelAPI.
KernelAPI это недокументированное API (небольшая часть функций всё же описана в WDK, но не все).
В кругах низкоуровневых программистов функции KernelAPI ещё называют сервисами (или подпрограммами системных служб).

Дальше опускаться уже не будем - там только слой аппаратных абстракций (HAL) и само железо.
В двух словах: HAL транслирует код в оперативной памяти таким образом, чтобы другие микроконтроллеры смогли обработать запросы от центрального процессора и предоставить ответы.
Вот одна из Hal-функций, которые начиная с поздних версий Windows 10, переехали из hal.dll в ядро ОС ntoskrnl.exe
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
NTHALAPI
BOOLEAN
HalTranslateBusAddress(
    _In_ INTERFACE_TYPE InterfaceType,
    _In_ ULONG BusNumber,
    _In_ PHYSICAL_ADDRESS BusAddress,
    _Inout_ PULONG AddressSpace,
    _Out_ PPHYSICAL_ADDRESS TranslatedAddress
    );
 
//
// Values for AddressSpace parameter of HalTranslateBusAddress
//
//      0x0         - Memory space
//      0x1         - Port space
//      0x2 - 0x1F  - Address spaces specific for Alpha
//                      0x2 - UserMode view of memory space
//                      0x3 - UserMode view of port space
//                      0x4 - Dense memory space
//                      0x5 - reserved
//                      0x6 - UserMode view of dense memory space
//                      0x7 - 0x1F - reserved
//
Итак, подведём итоги:
1. операционная система Windows предоставляет API интерфейсы, расположенные в библиотеках DLL.
2. пользовательское приложение вызывает API, реализованное в библиотеках DLL.
3. большинство функций API в конечном итоге вызывают подпрограммы системных служб (сервисы) в ntoskrnl.exe

Все менеджеры, утилиты, программы и т.д. используют API.
API не может использовать менеджеры и утилиты в качестве запуска службы и прочего.
API это программный интерфейс, выполняющий определенные команды, которыми пользуются программисты при разработке приложений.
Метки c, c++, winapi
Размещено в Без категории
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 0
Комментарии
 
Новые блоги и статьи
Debian 13: Установка Lazarus QT5
ВитГо 09.05.2026
Эта инструкция моя компиляция инструкций volvo https:/ / www. cyberforum. ru/ blogs/ 203668/ 10753. html и его же старой инструкции по установке Lazarus с gtk2. . .
Нейросеть на алгоритме "эстафета хвоста" как перспектива.
Hrethgir 06.05.2026
На десерт, когда запущу сервер. Статья тут https:/ / habr. com/ ru/ articles/ 1030914/ . Автор я сам, нейросеть только помогает в вопросах которые мне не известны - не знаю людей которые знали-бы. . .
Асинхронный приём данных из COM-порта
Argus19 01.05.2026
Асинхронный приём данных из COM-порта Купил на aliexpress термопринтер QR701. Он оказался странным. Поключил к Arduino Nano. Был очень удивлён. Наотрез отказывается печатать русские буквы. Чтобы. . .
попытка написать игровой сервер на C++
pyirrlicht 29.04.2026
попытка написать игровой сервер на плюсах с открытым бесконечным миром. возможно получится прикрутить интерпретатор питон для кастомизации игровой логики. что есть на текущий момент:. . .
Контроль уникальности выбранного документа-основания при изменении реквизита
Maks 28.04.2026
Алгоритм из решения ниже разработан на примере нетипового документа "ЗаявкаНаРемонтСпецтехники", разработанного в КА2. Задача: уведомлять пользователя, если указанная заявка (документ-основание). . .
Благородство как наказание
Maks 24.04.2026
У хорошего человека отношения с женщинами всегда складываются трудно. А я человек хороший. Заявляю без тени смущения, потому что гордиться тут нечем. От хорошего человека ждут соответствующего. . .
Валидация и контроль данных табличной части документа перед записью
Maks 22.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа, разработанного в КА2. Задача: контроль и валидация данных табличной части документа перед записью с учетом регламента компании. . .
Отчёт о затраченных материалах за определенный период с макетом печатной формы
Maks 21.04.2026
Отчёт из решения ниже размещён в конфигурации КА2. Задача: разработка отчёта по затраченным материалам за определённый период, с возможностью вывода печатной формы отчёта с шапкой и подвалом. В. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru