Este artigo mostra como invocar de funções e passar parâmetros a essas funções, em assembly x86. São apresentadas as convenções do C e do Pascal.
Segue um exemplo de um programa em C e de uma solução equivalente em assembly.
C | Assembly |
int main() { int x=5, y=7, z; z = soma(x,y); } |
section  .data x   dd                 5 y   dd                 7 z   dd                 0 |
section .text push             dword[y] push             dword[x] call                soma add               esp, 8 mov              dword[z], eax |
|
int soma(int a, int b) { return a+b; } |
soma: push             ebp mov              ebp, esp mov              eax, [ebp+8] add               eax, [ebp+12] pop               ebp ret |
Como se pode ver no exemplo acima, o C carrega os parâmetros da direita para a esquerda. Assim, o primeiro parâmetro a ser carregado em stack é o y e depois o x. Por fim, invoca a função.
Quando o controlo retorna da função, o programa de chamada tem que acertar a stack. Isso é feito, adicionando 8 unidades ao stack pointer, 4 unidades por cada parâmetro carregado, pois num máquina a 32 bits, todos os movimentos em stack são a 32 bits.
De seguida, apresenta-se um exemplo de um programa em Pascal e de uma solução equivalente em assembly.
Pascal | Assembly |
program somar; var x, y, z: integer;function soma(a,b: integer): integer; begin soma := a+b; end;begin x := 5; y := 7; z := soma(x,y); end. |
section   .data x  dd                5 y  dd                7 z  dd                0 |
section .text push           dword[x] push           dword[y] call              soma mov            dword[z], eax |
|
soma: push           ebp mov            ebp, esp mov            eax, [ebp+12] add             eax, [ebp+8] pop             ebp ret               8 |
Como se pode ver no exemplo acima, o Pascal carrega os parâmetros da esquerda para a direita. Assim, o primeiro parâmetro a ser carregado em stack é o x e depois o y. Por fim, invoca a função.
Na convenção do Pascal, o acerto da stack é feito dentro da função, na instrução ret. O ret 8 adiciona 8 unidades ao stack pointer, 4 unidades por cada parâmetro carregado.
Como o acerto da stack é feito dentro da função, é obrigatório passar exatamente 2 parâmetros quando se invoca esta função.
Em C, por outro lado, como o acerto da stack é feito no programa de chamada, podemos passar o número de parâmetros que entendermos, mesmo que sejam diferentes, em número, do que a função espera.