Naked
 
Запись функции без кода пролога/эпилога

Синтаксис

{Sub | Function} identifier Naked [calling_convention] ( param_list ) [As data_type]
asm_statements
End {Sub | Function}

Параметры

identifier - имя процедуры.
calling_convention - конвенция вызова процедуры - может быть cdecl, pascal, или stdcall
asm_statements - код в теле процедуры. Код для обработки параметров и возвращения значений должен быть сделан вручную. Обратите внимание, что методы могут меняться, в зависимости от конвенции вызова.
param_list - передаваемые в процедуру параметры.
data_type - тип данных функции.

Описание

Naked позволяет программисту писать процедуры без созданного компилятором кода пролога и эпилога. Это полезно при написании небольших, быстрых функций в блоке Asm без каких-либо ненужных накладных расходов.

Пример

'' Naked cdecl функция
Function subtract_c Naked cdecl _   '' параметры кладутся в стек в обратном порядке при декларации
    ( _
        ByVal a As Integer, _
        ByVal b As Integer _        '' параметр кладется в стек первым
    ) As Integer
   
    Asm
        mov eax, dword Ptr [esp+4]  '' eax = a
        Sub eax, dword Ptr [esp+8]  '' eax -= b
        ret                         '' возвращаем результат в eax
    End Asm
   
End Function

Print subtract_c( 5, 1 ) '' 5 - 1

''---------------------------------------------------------------------------------------------------------------------

'' Naked stdcall функция
Function subtract_s Naked stdcall _ '' параметры кладутся в стек в обратном порядке при декларации
                         _          '' вызванная процедура отвечает за удаление параметров из стека
                         _          ''   (добавления константы в инструкцию RET указывает количество байт, предназначенных для освобождения)
    ( _
        ByVal a As Integer, _
        ByVal b As Integer _        '' параметр кладется в стек первым
    ) As Integer
   
    Asm
        mov eax, dword Ptr [esp+4]  '' eax = a
        Sub eax, dword Ptr [esp+8]  '' eax -= b
        ret 8                       '' возвращаем результат в eax и указываем 8 байт (2 integers) для освобождения
    End Asm
   
End Function

Print subtract_s( 5, 1 ) '' 5 - 1 

''---------------------------------------------------------------------------------------------------------------------

'' Naked pascal function
Function subtract_p Naked pascal _  '' параметры кладутся в стек в том же порядке, что и при декларации
                         _          '' вызванная процедура отвечает за удаление параметров из стека
                         _          ''   (добавления константы в инструкцию RET указывает количество байт, предназначенных для освобождения)
    ( _
        ByVal a As Integer, _       '' параметр кладется в стек первым
        ByVal b As Integer _
    ) As Integer
   
    Asm
        mov eax, dword Ptr [esp+8]  '' eax = a
        Sub eax, dword Ptr [esp+4]  '' eax -= b
        ret 8                       '' возвращаем результат в eax и указываем 8 байт (2 integers) для освобождения
    End Asm
   
End Function

Print subtract_p( 5, 1 ) '' 5 - 1


'' Naked cdecl функция
'' плюс регистр ecx, сохраняем в asm блоке, создавая пользовательский стек
Function subtract_cp Naked cdecl _      '' параметры кладутся в стек в обратном порядке при декларации
    ( _
        ByVal a As Integer, _
        ByVal b As Integer _            '' параметр кладется в стек первым
    ) As Integer
   
    Asm
        push ebp                        '' кладем значение ebp в стек   => esp -= 4
        mov ebp, esp                    '' ebp = esp
                                        ''    => создаем пользовательский стек на 4 байта выше стека вызовов
        push ecx                        '' кладем значение ecx в пользовательский стек => esp -= 4
        mov eax, dword Ptr [(ebp+4)+4]  '' eax = a   (дополнительное смещение +4 байта, только из-за 'push ebp')
        mov ecx, dword Ptr [(ebp+8)+4]  '' ecx = b   (дополнительное смещение +4 байта, только из-за 'push ebp')
        Sub eax, ecx                    '' eax -= ecx
        pop ecx                         '' Восстанавливаем значение ecx из пользовательского стека => esp += 4
        mov esp, ebp                    '' esp = ebp
        pop ebp                         '' Восстанавливаем значение ebp из стека => esp += 4
                                        ''    => отменяя пользовательский стек
        ret                             '' возвращаем результат в eax
    End Asm
   
End Function

Print subtract_cp( 5, 1 ) '' 5 - 1

Различия платформ

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

Отличия от QB

  • Новое в FreeBASIC

См. также