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.