Convenção de Chamadas de Procedimentos e Funções

Escrito em 27 de julho de 2007 em Delphi por Leonel Togniolli

A execução de um programa não é nada mais do que uma série de instruções geradas pelo compilador sendo executadas em sequência. Algumas delas desviam a execução para um trecho anterior ou posterior de um código, criando laços de repetição ou condicionais. Outras, desviam o fluxo para um trecho diferente de código, que é executado e retorna a execução para onde foi chamado.

Esse trecho diferente de código não é nada mais do que um procedimento que foi chamado. É interessante pensar como ele sabe para onde desviar a execução quando terminado, voltando para onde estava: o código chamador deve colocar na pilha (que nada mais é do que um trecho de memória reservado pelo processo) o endereço de retorno.

Só que um procedimento, para ter uma maior utilidade, pode aceitar parâmetros ou retornar valores. O código chamador deve ter uma forma de passar esses parâmetros para que o novo procedimento possa usá-los. Uma forma é colocá-los na pilha, da mesma forma foi feito com o endereço de retorno. Outra é passá-los nos registradores do processador (possivelmente de uma forma mais eficiente que a anterior). Tendo vários parâmetros, em que ordem são passados? Quem vai remover os valores da pilha, o procedimento chamado ou o chamador?

Tanto faz, desde que o código que está efetuando a chamada e o que está sendo chamado concordem com isso. Existem alguns padrões, e eles são chamados de “convenção de chamadas”. Eles diferem nos items citados acima, definindo a forma da chamada.

São convenções de chamada suportadas pelo Delphi: register, pascal, cdecl, stdcall e safecall. Para especificar a convenção de chamada de um procedimento qualquer, basta colocar a convenção desejada após a declaração da função:

procedure Teste(Parametro: Integer) ; stdcall;

A convenção padrão no Delphi, caso não seja especificada, é register, que como o nome sugere, passa quantos parâmetros forem possível em registradores e o resto na pilha, ao contrário da convenção geralmente padrão com compiladores C, cdecl, que utiliza a pilha exclusivamente. Não é necessário saber exatamente os detalhes de cada uma, podendo deixar isso para o compilador, desde que saibamos quando usar cada uma delas.

Não especificamos a convenção geralmente por falta de necessidade – a padrão é o suficiente para a maioria dos casos, e se o compilador está gerando o código que efetuará a chamada e o que será chamado, ele deve saber como passar os parâmetros. Conhecer a convenção de chamada é importante quando for necessário chamar código que é externo à sua aplicação – em uma DLL geralmente. Possívelmente escrita em outra linguagem. Só sabendo a convenção de chamada e a especificando corretamente você irá estar passando os parâmetros de uma forma que ela reconheça e retorne corretamente. Mas isso é assunto para outro artigo.


Um comentário em 'Convenção de Chamadas de Procedimentos e Funções' »

Assine os comentários usando RSS ou faça um TrackBack para 'Convenção de Chamadas de Procedimentos e Funções'.

Em 29 de julho de 2007 às 17:51

[...] Convenção de Chamadas de Procedimentos e Funções [...]