opa galera do invaders ^^
estive com uma tremenda dúvida sobre onde por este post, poderia ser na area de C++, pq é a linguagem que sera usada para testes, ou aqui mesmo na área geral, pq o foco real é assembly, então eu fiz um "papai do céu" e deu esta área mesmo xD
bom, vamos lá, no assembly, existem 3 tipos de funções ( na realidade são calling conventions ) que os compiladores (de qualquer linguagem) adotam, são eles:
cdecl
stdcall
fastcall
existe também um 4º, o thiscall, usado em métodos de classe e comumente usado para métodos nas classes C++. Este, por ser mais complexo, não será falado aqui.
CDECL:
este é o tipo de função mais comum usado por programadores asm e normalmente as funções C e C++ são __cdecl por default.
Ele basicamente trata-se de, "pushar" os parâmetros (na ordem inversa) na pilha, executar a função com um call e limpar os parametros da pilha, comumente com um add esp, numero_de_bytes
um exemplo:
em C:
e sua função equivalente em assembly ( note a inversão da ordem dos parâmetros ):Código:int soma( int a, int b ) { return a + b; } int main() { int result = soma(1, 1); return 0; }
a principal característica e vantagem do tipo cdecl, deve-se ao fato de que a limpeza da stack é feita fora da função, logo após o call, isso permite que funções com parametros indefinidos tenham, no fim da sua execução, a pilha limpa.Código:push 1 ; segundo parâmetro push 1 ; primeiro parâmetro call soma ; chamando a função add esp, 8 ; limpando a pilha, como cada parametro tem o tamanho de uma ; dword (4 bytes), limpamos 8 bytes soma: push ebp mov ebp, esp mov eax, dword ptr[ebp + 8] ; pegando primeiro parametro add eax, dword ptr[ebp + 12] ; e somando com o segundo ; obs: eax = valor de retorno mov esp, ebp pop ebp ret ; sai da função
posso dar um exemplo da função printf do C, cujos parametros são:
printf( const char* str, ...);
STDCALL:
este é o tipo de função usado por alguns programadores asm e normalmente as funções do Pascal e Objetive Pascal são __stdcall por default.
Ele basicamente trata-se de, "pushar" os parâmetros (na ordem inversa) na pilha, executar a função com um call e, diferentemente do cdecl, podemos omitir o add esp, numero_de_bytes, pois a pilha é limpa pelo ret da função
Exemplo no C:
e sua função equivalente no assembly:Código:int __stdcall soma( int a, int b ) { return a + b; } int main() { int result = soma( 1, 1); return 0; }
infelizmente, a unica desvantagem se deve a este tipo de função não suportar parametros indefinidos.Código:push 1 ; segundo parametro push 1 ; primeiro parametro call soma ; chamamos a função ; não é mais preciso limpar a stack aqui =) soma: push ebp mov ebp, esp mov eax, dword ptr[ebp + 8] ; pega primeiro parametro add eax, dword ptr[ebp + 12] ; e soma com o segundo ; obs: eax = valor de retorno mov esp, ebp pop ebp ret 8 ; note aqui a diferença para o cdecl =D
FASTCALL:
este tipo, é o mais remoto de se ver alguem usar, ele trata-se basicamente de:
enviar os dois primeiros parametros para os registradores ecx e edx respectivamente e, caso haja um terceiro, vai para a stack ( necessitando limpá-la, ficando a seu critério o método de limpeza do stdcall e cdecl ).
Exemplo em C:
E seu equivalente em assembly:Código:int __fastcall soma3( int a, int b, int c ) { return a + b + c; } int main() { int result = soma(1, 2, 3); return 0; }
fastcall é muito usada para funções triviais como essa, pois, como seu nome sugere, torna-se de rapida chamadaCódigo:mov ecx, 1 ; primeiro parametro mov edx, 2 ; segundo parametro push 3 ; terceiro parametro call soma ; chamamos a função add esp, 4 ; no caso, escolhi limpar a pilha da forma do cdecl soma: push ebp mov ebp, esp mov eax, ecx ; pego o primeiro parametro add eax, edx ; e somo com o segundo parametro add eax, dword ptr[ebp + 8] ; e depois somo com o terceiro ; obs: eax = valor de retorno mov esp, ebp pop ebp ret
bem, é só, espero que tenham gostado
abraços



Responder com Citação
