Может кто-нибудь объяснить __declspec (голый), пожалуйста? - PullRequest
9 голосов
/ 11 июня 2010

Я смотрю на перенос скриптового движка, написанного для Windows, на Linux;это для платформы визуализации Winamp AVS.Я не уверен, возможно ли это в данный момент.Из того, что я могу сказать, код берет адреса функций C nseel_asm_atan и nseel_asm_atan_end и сохраняет их в таблице, на которую он может ссылаться во время выполнения кода.

Я посмотрел документацию MS,но я не уверен, что на самом деле делает __declspec(naked).Что такое пролог и эпилог, упомянутый в документации?Это связано с соглашениями о вызовах Windows?Это портативный?Знаете ли вы какие-нибудь примеры на основе Linux, использующие подобные методы?

static double (*__atan)(double) = &atan;
__declspec ( naked ) void nseel_asm_atan(void)
{
  FUNC1_ENTER

  *__nextBlock = __atan(*parm_a);

  FUNC_LEAVE
}
__declspec ( naked ) void nseel_asm_atan_end(void) {}

Ответы [ 2 ]

8 голосов
/ 12 июня 2010

В основном, пролог функции устанавливает кадр стека для локальных переменных, а эпилог заботится о его очистке. Обычно это делается автоматически компилятором. Если вы используете __declspec(naked), настройка этого стекового фрейма будет зависеть от вас, так что это даст вам больше гибкости.

Есть много ссылок: здесь , здесь , также здесь и более.

Компилятор GNU gcc также поддерживает naked, но, очевидно, не для x86: поиск «naked» на странице (я не пытался проверить, работает ли он на x86)

2 голосов
/ 21 августа 2018

из википедии пролог и эпилог функции:

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

Чтобы компилятор не генерировал автоматическидополнительный код внутри вашей функции, всегда объявляйте функцию, используя соглашение __declspec(naked).

давайте посмотрим на эту функцию:

void myTrampoline()
{
__asm {
  PUSHFD
  PUSHAD
  CALL jumpHookCallback
  POPAD
  POPFD
  POP EAX
  MOV AL, 1
  POP EDI
  POP ESI
  JMP [restoreJumpHook]
 }
}

теперь компилятор сгенерирует код, который манипулируеткадр стека функции, называемой прологом и эпилогом функции, и результат будет выглядеть следующим образом

;Prologue
push ebp
mov ebp, esp
sub esp, N

PUSHFD
PUSHAD
CALL jumpHookCallback
POPAD
POPFD
POP EAX
MOV AL, 1
POP EDI
POP ESI
JMP [restoreJumpHook]

;Epilogue
mov esp, ebp
pop ebp
ret

, но если мы используем __declspec(naked), не будет Prologue нет Epilogue

void __declspec(naked) myTrampoline()
{
__asm {
  PUSHFD
  PUSHAD
  CALL jumpHookCallback
  POPAD
  POPFD
  POP EAX
  MOV AL, 1
  POP EDI
  POP ESI
  JMP [restoreJumpHook]
 }
}

и результат будет выглядеть так:

    PUSHFD
    PUSHAD
    CALL jumpHookCallback
    POPAD
    POPFD
    POP EAX
    MOV AL, 1
    POP EDI
    POP ESI
    JMP [restoreJumpHook]
...