Repository 32bit  Forum
Repository 64bit  Wiki

Assembler inline

Forum dedicato alla programmazione.

Moderatore: Staff

Regole del forum
1) Citare sempre la versione di Slackware usata e la versione del Kernel. Questi dati aiutano le persone che possono rispondere.
2) Specificare sempre il tipo di shell (bash, sh, csh, etc...)
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 dell'ultima regola 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 19: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 15:14

Re: Assembler inline

Messaggioda robbybby » ven feb 29, 2008 21: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: 1077
Iscritto il: sab dic 16, 2006 11: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 2: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 15:14

Re: Assembler inline

Messaggioda Blizzard » dom mar 02, 2008 12: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 23: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 15: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 15:14

Re: Assembler inline

Messaggioda Blizzard » dom mar 02, 2008 17: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 23: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 17: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 15:14

Re: Assembler inline

Messaggioda 414N » gio mar 06, 2008 19: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: 2844
Iscritto il: mer feb 13, 2008 17:19
Località: Bulagna
Slackware: 14.0 (x64)
Kernel: 3.2.29
Desktop: LXDE

Re: Assembler inline

Messaggioda Calzo » gio apr 17, 2008 19: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 22:21
Località: MN
Slackware: 10.2 | 13
Desktop: Fluxbox | KDE


Torna a Programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 2 ospiti