Запись функции без кода пролога/эпилога
Синтаксис
Параметры
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
См. также