Repository 32bit  Forum
Repository 64bit  Wiki

Assembler inline

Forum dedicato alla programmazione.

Moderatore: Staff

Regole del forum
1) Citare in modo preciso il linguaggio di programmazione usato.
2) Se possibile portare un esempio del risultato atteso.
3) Leggere attentamente le risposte ricevute.
4) Scrivere i messaggi con il colore di default, evitare altri colori.
5) Scrivere in Italiano o in Inglese, se possibile grammaticalmente corretto, evitate stili di scrittura poco chiari, quindi nessuna abbreviazione tipo telegramma o scrittura stile SMS o CHAT.
6) Appena registrati è consigliato presentarsi nel forum dedicato.

La non osservanza delle regole porta a provvedimenti di vari tipo da parte dello staff, in particolare la non osservanza della regola 5 porta alla cancellazione del post e alla segnalazione dell'utente. In caso di recidività l'utente rischia il ban temporaneo.

Assembler inline

Messaggioda afterjames » ven feb 29, 2008 18:52

Salve a tutti..Sono un neofita dell'assembler, ho provato a realizzare una semplice funzione che esegue una somma tra due interi senza segno..Purtroppo i risultati sono deludenti!Non capisco se è sbagliato il mio listato, o se c'è qualcosa che mi sfugge relativamente alla sintassi AT&T.Ho fatto così:

Codice: Seleziona tutto
#include<stdio.h>

unsigned int miaVar=56;
unsigned int miaVar2=299;
unsigned int somma;
int main(void){
   asm("movl miaVar,%ebx\n\t"
          "movl miaVar2,%ecx\n\t"
          "movl $0,%eax\n\t"
          "pushl %ebx\n\t"
          "pushl %ecx\n\t"
          "call somma_r\n\t"
          "addl $8,%esp\n\t"
          "movl %eax,somma\n\t"     
       "somma_r:pushl %ebp\n\t"
           "movl %ebp,%esp\n\t"        
                "movl 12(%ebp),%eax\n\t"
           "addl 8(%ebp),%eax\n\t"
                "movl %ebp,%esp\n\t"
           "popl %ebp\n\t"
           "ret\n\t");


printf("Valore %u \n",somma);
return 0;       

}



Ci sono alcune istruzioni inutili, tipo le movl su ebp ed esp, ma non credo siano quelli i problemi.La Call da problemi.Le label si inseriscono così?"<nome_label>:"
afterjames
Linux 1.0
Linux 1.0
 
Messaggi: 64
Iscritto il: lun gen 14, 2008 14:14

Re: Assembler inline

Messaggioda robbybby » ven feb 29, 2008 20:46

Non conosco l'assembler AT&T, ma, a prima vista, mi sembra di notare una mancata pulizia dello stack dopo la chiamata: hai due push (ebx e ecx) ma nessun pop che li toglie dallo stack, ne' nel chimato, ne' nel chiamante.
Inoltre prima di "somma_r:" ci andrebbe un ret o un jump.
Ripeto: non conosco l'assembler in questione: le mie sono sono considerazioni generali.
Avatar utente
robbybby
Linux 3.x
Linux 3.x
 
Messaggi: 1175
Iscritto il: sab dic 16, 2006 10:48
Località: Fra Trantor e Terminus
Slackware: 13.1 / 64 bit
Kernel: 3.3.x
Desktop: KDE 4.4.5

Re: Assembler inline

Messaggioda afterjames » sab mar 01, 2008 1:38

Ho trovato un'istruzione sbagliata sulla funzione.La versione giusta è:


"somma_r: pushl %ebp\n\t"
"movl %esp,%ebp\n\t"
"movl 12(%ebp),%eax\n\t"
"addl 8(%ebp),%eax\n\t"
"movl %ebp,%esp\n\t"
"popl %ebp\n\t"
"ret\n\t");


Però non funziona ugualmente!Riguardo la pulizia dello stack, non c'è bisogno di fare le pop, dopo la Call faccio un incremento di 8 byte pari proprio alla dimensione dei due parametri della funzione.La funzione dovrebbe essere giusta, ho provato a far generare l'assembler con gcc -S ed ho ottenuto praticamente quella che ho scritto..Grazie comunque
afterjames
Linux 1.0
Linux 1.0
 
Messaggi: 64
Iscritto il: lun gen 14, 2008 14:14

Re: Assembler inline

Messaggioda Blizzard » dom mar 02, 2008 11:04

ciao,
ad occhio e croce ho visto che hai definito una funzione dentro il main.... non lo so se si può fare e soprattutto senza conseguenze impreviste....

Codice: Seleziona tutto
#include<stdio.h>

    unsigned int miaVar=56;
    unsigned int miaVar2=299;
    unsigned int somma;
    int main(void){
       asm("movl miaVar,%ebx\n\t"
             "movl miaVar2,%ecx\n\t"
             "movl miaVar,%eax\n\t"
             "addl %ecx,%eax\n\t"
             "movl %eax,somma\n\t");


       printf("Valore %u \n",somma);
       return 0;       

    }


così funge tutto.... ma mi dirai "Grazie al" non era quello che volevo.... tuttavia hai provato a dichiarare, sempre inline la funzione separatamente???
oppure a scrivere quel codice totalmente asm?
a quanto vedo fai tutto con l'asm, non ho capito a cosa ti serve quella parte dichiarativa di C

ciao
Gio
Avatar utente
Blizzard
Master
Master
 
Messaggi: 1509
Iscritto il: mar gen 02, 2007 22:53
Nome Cognome: Giovanni Santostefano
Slackware: 12.2
Kernel: 2.6.27.7-smp
Desktop: Fluxbox

Re: Assembler inline

Messaggioda afterjames » dom mar 02, 2008 14:38

Grazie.Ho fatto così:

Codice: Seleziona tutto
#include<stdio.h>
unsigned int miaVar=56;
unsigned int miaVar2=29;
unsigned int somma=0;
void s(){
        asm("somma_r:pushl %ebp\n\t"
              "movl %esp,%ebp\n\t"        
                   "movl 12(%ebp),%eax\n\t"
               "addl 8(%ebp),%eax\n\t"
                    "movl %ebp,%esp\n\t"
               "popl %ebp\n\t"
                "ret\n\t");

}
int main(void){
   asm("pusha\n\t"            // Salva: EAX, EBX, ECX, EDX, ESI, EDI, EBP
       "movl miaVar,%ebx\n\t"
       "movl miaVar2,%ecx\n\t"
       "movl $0,%eax\n\t"
       "pushl %ebx\n\t"
       "pushl %ecx\n\t"
       "call somma_r \n\t"
       "addl $8,%esp\n\t"
       "movl %eax,somma\n\t"
       "popa\n\t");          // Salva: EAX, EBX, ECX, EDX, ESI, EDI, EBP


printf("Valore %u \n",somma);
return 0;       
}
+

Ed ora funziona.Oltre a dover dichiarare la funzione fuori dal main, bisogna salvare all'inizio del main i registri utilizzati e poi ripristinarli.Uso ASM perchè ho maggiore flessibilità, e non ho bisogno di fare file separati da integrare poi in fase di linking.Mi sembra la soluzione più immediata.
afterjames
Linux 1.0
Linux 1.0
 
Messaggi: 64
Iscritto il: lun gen 14, 2008 14:14

Re: Assembler inline

Messaggioda Blizzard » dom mar 02, 2008 16:24

ciao

senti... per fa na cosa più leggibile, perchè non scrivi tipo così?
Codice: Seleziona tutto
asm("movl miaVar,%ebx; \
      movl miaVar2,%ecx; \
      movl miaVar,%eax; \
      addl %ecx,%eax; \
      movl %eax,somma;");
      

se non hai esigenze particolari, tutti sti \t\n non so troppo belli.... a me scritto così assembla lo stesso

Uso ASM perchè ho maggiore flessibilità, e non ho bisogno di fare file separati da integrare poi in fase di linking.Mi sembra la soluzione più immediata.

capito!

ciao
Gio
Avatar utente
Blizzard
Master
Master
 
Messaggi: 1509
Iscritto il: mar gen 02, 2007 22:53
Nome Cognome: Giovanni Santostefano
Slackware: 12.2
Kernel: 2.6.27.7-smp
Desktop: Fluxbox

Re: Assembler inline

Messaggioda afterjames » dom mar 02, 2008 16:28

ciao

senti... per fa na cosa più leggibile, perchè non scrivi tipo così?

Codice: Seleziona tutto
    asm("movl miaVar,%ebx; \
          movl miaVar2,%ecx; \
          movl miaVar,%eax; \
          addl %ecx,%eax; \
          movl %eax,somma;");
           


se non hai esigenze particolari, tutti sti \t\n non so troppo belli.... a me scritto così assembla lo stesso



Grazie! :thumbright:
afterjames
Linux 1.0
Linux 1.0
 
Messaggi: 64
Iscritto il: lun gen 14, 2008 14:14

Re: Assembler inline

Messaggioda 414N » gio mar 06, 2008 18:38

Più che altro, dato che praticamente tutto il programma è scritto in assembly, non fai meglio a inglobarlo in una routine, schiaffarlo dentro un file assembly (.s) e richiamare la funzione somma dal programma C?
Certo, dovrai stare attento al passaggio degli argoment C<->ASM, ma una volta sistemato questo avrai reso il programma più guardabile e più riusabile.
Avatar utente
414N
Iper Master
Iper Master
 
Messaggi: 2882
Iscritto il: mer feb 13, 2008 16:19
Località: Bulagna
Slackware: 14.0 (x64)
Kernel: 3.2.29
Desktop: LXDE

Re: Assembler inline

Messaggioda Calzo » gio apr 17, 2008 18:37

afterjames ha scritto:Oltre a dover dichiarare la funzione fuori dal main [...]

Bhè non è verissimo. Tu puoi mettere le funzioni praticamente dovunque ti pare (con l'asm tutto è possibile :badgrin:), anche se la soluzione a cui sei arrivato è sicuramente più chiara, IMHO; il vero problema è che nel listato originale tu fai queste operazioni:
Codice: Seleziona tutto
 [...]
       "call somma_r\n\t"
       "addl $8,%esp\n\t"
       "movl %eax,somma\n\t"
       "somma_r: pushl %ebp\n\t"
[...]

ma questo è sbagliato perchè tu fai una call dalla quale ritorni per poi proseguire, ma se prosegui linearmente vai ad eseguire ancora il codice puntato da somma_r il quale poi esegue delle operazioni sul base pointer e quando incontra RET esce dalla funzione main... e insomma succede un casino.
La soluzione è semplicemente nel mettere un jump incondizionato se vuoi mantenere la struttura del programma originale:
Codice: Seleziona tutto
asm("movl miaVar,%ebx\n\t"
       "movl miaVar2,%ecx\n\t"
       "movl $0,%eax\n\t"
       "pushl %ebx\n\t"
       "pushl %ecx\n\t"
       "call somma_r\n\t"
       "addl $8,%esp\n\t"
       "movl %eax,somma\n\t"
      "jmp salto_;\n\t"
       "somma_r: pushl %ebp\n\t"
       "movl %esp,%ebp\n\t"
       "movl 12(%ebp),%eax\n\t"
       "addl 8(%ebp),%eax\n\t"
       "movl %ebp,%esp\n\t"
       "popl %ebp\n\t"
       "ret\n\t"
      "salto_:");

afterjames ha scritto:bisogna salvare all'inizio del main i registri utilizzati e poi ripristinarli

neanche questo è strettamente necessario, anche se anche io preferisco metterlo ;)

Una cosa che forse ti può interessare: per "aumentare la visibilità" del codice puoi scrivere le funzioni così
Codice: Seleziona tutto
void funzione();
asm("funzione:\n\t"
        "pushl %ebp\n\t"
   "movl %esp,%ebp\n\t"        
        [...]
        "ret\n\t");

Non so se lo sapevi già: io l'ho scoperto recentemente spulciando un kernel (Linux ovviamente :thumbright:). Questo ti permette anche di rilocare la funzione dove preferisci e di chiamarla come una funziona C. Inoltre aggiunge un piccolo livello di ottimizzazione in quanto elimini le istruzioni push %ebp, mov %ebp e il ret finale che la funzione s() che avevi definito aggiunge necessariamente (almeno a meno di ottimizzazioni del compilatore che non ho provato).

bye
Avatar utente
Calzo
Linux 2.0
Linux 2.0
 
Messaggi: 112
Iscritto il: sab ott 06, 2007 21:21
Località: MN
Slackware: 10.2 | 13
Desktop: Fluxbox | KDE


Torna a Programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 1 ospite