Assembly com parametros

1. Assembly com parametros

???
gokernel

(usa Linux Mint)

Enviado em 27/07/2012 - 18:36h


Olá pessoal !!!

Tenho uma funcao em C "sem paremetros" que utiliza assembly para executar com "efeito de parametros:

Esse exemplo eh somente para exemplificar ... eh +ou- assim:

[code]

void teste (int x, int y, int z)
{
printf ("valor: %d - %d - %d\n", x, y, z);
}

void *func = teste;


// argumento 1:
__asm__ __volatile__ ("movl %0, %%eax" : /*OutPut*/ : "a"( 123 ));
__asm__ __volatile__ ("movl %eax, (%esp)");

// argumento 2:
__asm__ __volatile__ ("movl %0, %%eax" : /*OutPut*/ : "a"( 444 ));
__asm__ __volatile__ ("movl %eax, 4(%esp)");

// argumento 3:
__asm__ __volatile__ ("movl %0, %%eax" : /*OutPut*/ : "a"( 777 ));
__asm__ __volatile__ ("movl %eax, 8(%esp)");

// cast
( (void(*)()) (func) ) ();

[code]

PERGUNTA:
Alguem sabe como fazer para passar esses 3 argumentos usando assembly COM UM LOOP ("movl %eax, 8(%esp)"), apenas modificando esses valores entre aspas ( "4 ... 8" ) ???


Desde ja grato !



  


2. Re: Assembly com parametros

Perfil removido
removido

(usa Nenhuma)

Enviado em 28/07/2012 - 00:25h

Eu vou "rascunhar" a solução, mais ou menos do que fiz até o momento, também descrevendo prá quem observar o tópico:

Esse 4 é prá pular 4 bytes, 1 byte = 8 bits, então são 8 x 4 = 32 bits

Se fossem 64 bits, então eram 8, certo?

O registrador %esp guarda endereço de topo de pilha, endereços sempre de 32 bits, ou de tamanho de 4 bytes, então por isso de se pular de 4 em 4.

Então o que vejo, no momento, que estive prá completar uma coisa "pendurada" aqui e que tem a ver com isso, seria somar 4 diretamente em %esp, que é add $4, %esp

Isso também envolve duas possíveis condições: ou um símbolo no fim da pilha, que indique onde se encerra o desempilhamento de variáveis, igual ao caracter ' \ 0 ' de string de C, ou então o primeiro parâmetro da função ser obrigatioriamente o número de parâmetros que a função recebeu, igual ao primeiro caracter de string de Pascal, que diz o tamanho.

Você percebeu como na verdade é nada mais que um vetor de parâmetros?

É possível de a função receber um vetor? Pensando bem dará quase na mesma.

Continuando, a soma do valor 4 diretamente em %esp deve prosseguir até o último parâmetro da função ser lido, coisa que é controlada verificando se chegou ao "fim" da pilha (não é fim, seria o começo, mas é fim da verificação), ou então decrementando o número que veio como primeiro parâmetro a cada parâmetro lido até o mesmo chegar a zero e sair do loop.

É claro que pode ser necessária uma precaução para que %esp retorne ao valor original depois de tudo ter ocorrido.

Por enquanto é isto. Deve haver algo mais simples mas não sei se resume-se à sintaxe ou ao método usado.





3. Re: Assembly com parametros

???
gokernel

(usa Linux Mint)

Enviado em 28/07/2012 - 10:39h

@Listeiro 037:
" ... Se fossem 64 bits, então eram 8, certo?"

Correto.

" ... Então o que vejo, no momento, que estive prá completar uma coisa "pendurada" aqui e que tem a ver com isso, seria somar 4 diretamente em %esp, que é add $4, %esp "

Deste modo nao funcionaria pois tem que passar o REGISTRADOR (eax para a pilha(esp) com uma posicao("int 4")) assim: asm ("movl %eax, 4(%esp)");

Mesmo assim valeu pelo retorno !

E so para informação, aqui ta um exemplo completo C/Assembly:

DETALHE: esta sintax do assembly compilei com o GCC para windows em 32 bits ... portanto nao sei se é esta mesma sintax para o Linux;


//-------------------------------------------------------------------
//
// Exemplo C/Assembly de como chamar um PONTEIRO(funcao) sem parametro
//
//-------------------------------------------------------------------
#include <stdio.h>

void test (int a, int b, int c, int d)
{
printf ("a: %d, b: %d, c: %d, d: %d\n", a, b, c, d);
}


int main (void)
{
void *func = test;

// parametro 1: a
asm ("movl %0, %%eax" :/*out*/: "a"( 123 ));
asm ("movl %eax, (%esp)");

// parametro 2: b
asm ("movl %0, %%eax" :/*out*/: "a"( 444 ));
asm ("movl %eax, 4(%esp)");

// parametro 3: c
asm ("movl %0, %%eax" :/*out*/: "a"( 777 ));
asm ("movl %eax, 8(%esp)");

// parametro 4: d
asm ("movl %0, %%eax" :/*out*/: "a"( 1500 ));
asm ("movl %eax, 12(%esp)");

// CAST:
// executa o ponteiro como uma funcao com parametros ...
( (void(*)()) (func) ) ();

return 0;
}





4. Re: Assembly com parametros

Perfil removido
removido

(usa Nenhuma)

Enviado em 28/07/2012 - 13:31h

gokernel escreveu:

@Listeiro 037:
" ... Se fossem 64 bits, então eram 8, certo?"

Correto.

" ... Então o que vejo, no momento, que estive prá completar uma coisa "pendurada" aqui e que tem a ver com isso, seria somar 4 diretamente em %esp, que é add $4, %esp "

Deste modo nao funcionaria pois tem que passar o REGISTRADOR (eax para a pilha(esp) com uma posicao("int 4")) assim: asm ("movl %eax, 4(%esp)");

Mesmo assim valeu pelo retorno !

E so para informação, aqui ta um exemplo completo C/Assembly:

DETALHE: esta sintax do assembly compilei com o GCC para windows em 32 bits ... portanto nao sei se é esta mesma sintax para o Linux;


//-------------------------------------------------------------------
//
// Exemplo C/Assembly de como chamar um PONTEIRO(funcao) sem parametro
//
//-------------------------------------------------------------------
#include <stdio.h>

void test (int a, int b, int c, int d)
{
printf ("a: %d, b: %d, c: %d, d: %d\n", a, b, c, d);
}


int main (void)
{
void *func = test;

// parametro 1: a
asm ("movl %0, %%eax" :/*out*/: "a"( 123 ));
asm ("movl %eax, (%esp)");

// parametro 2: b
asm ("movl %0, %%eax" :/*out*/: "a"( 444 ));
asm ("movl %eax, 4(%esp)");

// parametro 3: c
asm ("movl %0, %%eax" :/*out*/: "a"( 777 ));
asm ("movl %eax, 8(%esp)");

// parametro 4: d
asm ("movl %0, %%eax" :/*out*/: "a"( 1500 ));
asm ("movl %eax, 12(%esp)");

// CAST:
// executa o ponteiro como uma funcao com parametros ...
( (void(*)()) (func) ) ();

return 0;
}




A coisa "pendurada" é algo que comecei a fazer aqui e parei. Está ligado a como alocar memória em assembly puro. É dar um "malloc()" sem pedir auxílio prá biblioteca do C. O problema é indexar as posições. No caso de nasm, o problema no momento é sintático.

O "rascunho" é meu porque senão posso dizer algo que esteja incorreto no rigor, como "somar" ao registrador %esp sem usar outro registrador, que foi o que aconteceu. Outro exemplo seria fazer divisão e não usar os registradores corretos por falta de atenção. Não há operação de dividir aqui, mas seria um exemplo.

Então o "rascunho" é a ideia em si e não o detalhe que obriga a funcionar só daquele jeito que senão não funciona.

Parte do que andei fazendo foi:

	popl	%eax
addl %eax, %esp


Havia um valor múltiplo de 4 na pilha.

Múltiplo de 4 pelo motivo informado e que seria 4 vezes o número de elementos envolvidos, ou no caso a quantidade de parâmetros.

Eu havia mandado esse valor prá lá para preservá-lo e usar depois para mudar o ponteiro da pilha.

O tal valor foi calculado somando-se 4 à alguma coisa cada vez que se empilhava.

No final esse valor múltiplo de 4 foi preservado na pilha e depois retirado.

Ele foi mandado prá %eax e depois incrementado à %esp para devolver o ponteiro de pilha a um valor antigo.

Computador trabalha apenas com dois tipos de valor: endereços de memória e conteúdo de endereços de memória.

%esp é alguma coisa que guarda um endereço de memória. Endereço este de alguma outra coisa.

No caso quando eu somei um valor ao ponteiro foi prá mandar ele apontar numa outra posição.

Que era a posição original do que fiz.

Somei e funcionou.

Se o endereço da pilha for mudado e depois for usado o conteúdo do topo dela e não o endereço, daí funciona.

Esse jeito de escrever 4(%esp), 8(%esp) foi feito prá não precisar ficar escrevendo soma de valores no %esp e talvez eu entenderia melhor testando como o código de máquina fica depois e vendo se apareceu instrução diferente. Isso nesse exemplo desse parágrafo que escrevi aqui.

Se no lugar do 4, 8 ... fosse colocado outro registrador ou variável que fizesse isso, funcionaria também.

Desculpe-me se fui muito detalhista, mas é que alguém mais pode ver e se interessar por assembly em Linux.

Exceto quando usam em eletrônica, o que sobrou foi muita coisa de DOS, TASM, MASM, além disso não creio que Assembly .NET exista.






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts