Отладка приложений

         

Соглашения о вызовах


Прежде чем перейти к другим инструкциям, сделаем краткий обзор соглашений о вызовах. Несколько инструкций, представленных в предыдущем разделе, могут обеспечить первоклассную отладку. Однако, чтобы показать, как нужно расшифровывать окно Disassembly, необходимо связать воедино процедуру вызова и соглашения о вызовах.

Соглашение о вызовах указывает, как нужно пересылать параметры в функцию и как происходит очистка стека, когда выполняется возврат из функции. Соглашение о вызовах диктует программист, который кодирует функцию. Этому соглашению должен следовать каждый, кто вызывает эту функцию. CPU не диктует каких-либо специальных соглашений о вызовах. Понимание этих соглашений облегчает отыскание параметров в окне Memory и определение потока операций языка ассемблера в окне Disassembly.

Существует всего пять соглашений о вызовах, но только три из них — наиболее общие: стандартный вызов (__stdcall), С-декларация (__cdecl) и this-вызов. Стандартный вызов и С-декларацию программист может указывать самостоятельно, а this-вызов применяется в С-программе автоматически, когда он задает способ передачи этого указателя. Два других соглашения о вызовах — это быстрый вызов (_fastcalll) и так называемые "голые" (naked) соглашения о вызовах. По умолчанию операционные системы Win32 не используют соглашение быстрого вызова в коде пользовательского режима, потому что оно не переносимо на другие CPU. Соглашение о "голых" вызовах применяется для программирования драйверов виртуальных устройств (VxD) и в тех случаях, когда программист хочет самостоятельно управлять прологом и эпилогом (об этом будет рассказано в главах, 12 к 14).

В табл. 6.3 перечисляются все соглашения о вызовах. Вспомним описание схемы декорирования1 имен для установки точек прерывания на системных функциях из главы 5. Из табл. 6.3 ясно, что схему декорирования имен диктует соглашение о вызовах.

 "Декорированное" имя в C++ — это генерируемая компилятором строка, содержащая, кроме собственно имени, символы, используемые компилятором или компоновщиком для получения информации о типе.
— Пер.

Читатель, никогда не встречавшийся с соглашениями о вызовах, может задаться вопросом: почему существуют различные их типы?. Различия между вызовами _cdecl и _stdcall довольно тонкие. При стандартном вызове вызываемая функция очищает стек, поэтому она должна точно "знать" количество ожидаемых параметров. В связи с этим функция стандартного вызова не может иметь переменного числа аргументов (как, например, printf). Поскольку для функций _cdeci стек очищает вызывающая программа, функции с переменным числом аргументов допустимы. Стандартный вызов используется по умолчанию для системных функций Win32, а также для функций языка Visual Basic.

Таблица 6.3. Соглашения о вызовах

Соглашение о вызове

Передача параметров

Поддержка стека

Декорирование имен

Замечания

_cdecl

Справа налево

Аргументы из стека удаляет вызывающая программа. Это единственное соглашение о вызовах, которое допускает переменные списки аргументов

Символ подчеркивания в качестве префикса перед именами функций, как в_Роо

Используется по умолчанию для функций С и C++

_ stdcall

Справа налево

Свои собственные аргументы из стека удаляет сама вызванная функция

Символ подчеркивания в качестве префикса перед именами функций и суффикс @ , за которым следует десятичное число байт в списке аргументов, как в_Роо@12

Используется почти всеми системными функциями и, по умолчанию, внутренними функциями Visual Basic

_ fastcall

Два первых DWORD-параметра передаются в регистрах ЕСХ и EDX; остальные передаются справа налево

Аргументы из стека удаляет вызывающая функция

Префикс @ перед именем и суффикс @ после него, за которым следует десятичное число байт в списке аргументов, как в ®Foo@12

Применяется только в Intel CPU. Это соглашение о вызовах используется по умолчанию для компиляторов Borland Delphi

this

Справа налево. Параметр this передается в регистре ЕСХ

Аргументы из стека удаляет вызывающая функция

Нет

Используется автомат-ски методами классов C++, если не указан стандартный вызов. Все СОМ-методы объявляются со стандартным вызовом




naked

  Справа налево

Аргументы из стека удаляет вызывающая функция

Нет

Используются драйверами виртуальных устройств VxD и когда программист нуждается в собственном прологе и эпилоге



Содержание раздела