2010-10-26 19 views
8
$ gcc -O2 -S test.c -----------------------(1) 
     .file "test.c" 
    .globl accum 
     .bss 
     .align 4 
     .type accum, @object 
     .size accum, 4 
    accum: 
     .zero 4 
     .text 
     .p2align 2,,3 
    .globl sum 
     .type sum, @function 
    sum: 
     pushl %ebp 
     movl %esp, %ebp 
     movl 12(%ebp), %eax 
     addl 8(%ebp), %eax 
     addl %eax, accum 
     leave 
     ret 
     .size sum, .-sum 
     .p2align 2,,3 
    .globl main 
     .type main, @function 
    main: 
     pushl %ebp 
     movl %esp, %ebp 
     subl $8, %esp 
     andl $-16, %esp 
     subl $16, %esp 
     pushl $11 
     pushl $10 
     call sum 
     xorl %eax, %eax 
     leave 
     ret 
     .size main, .-main 
     .section .note.GNU-stack,"",@progbits 
     .ident "GCC: (GNU) 3.4.6 20060404 (Red Hat 3.4.6-9)" 

Questo è un codice assembly generato da questo programma C:Analizzare codice assembly

#include <stdio.h> 
int accum = 0; 

int sum(int x,int y) 
{ 
    int t = x+y; 
    accum +=t; 
    return t; 
} 

int main(int argc,char *argv[]) 
{ 
    int i = 0,x=10,y=11; 
    i = sum(x,y); 
    return 0; 
} 

Inoltre, questo è il codice oggetto generato dal programma precedente:

$objdump -d test.o -------------------------(2) 

test.o:  file format elf32-i386 

Disassembly of section .text: 

00000000 <sum>: 
    0: 55      push %ebp 
    1: 89 e5     mov %esp,%ebp 
    3: 8b 45 0c    mov 0xc(%ebp),%eax 
    6: 03 45 08    add 0x8(%ebp),%eax 
    9: 01 05 00 00 00 00  add %eax,0x0 
    f: c9      leave 
    10: c3      ret 
    11: 8d 76 00    lea 0x0(%esi),%esi 

00000014 <main>: 
    14: 55      push %ebp 
    15: 89 e5     mov %esp,%ebp 
    17: 83 ec 08    sub $0x8,%esp 
    1a: 83 e4 f0    and $0xfffffff0,%esp 
    1d: 83 ec 10    sub $0x10,%esp 
    20: 6a 0b     push $0xb 
    22: 6a 0a     push $0xa 
    24: e8 fc ff ff ff   call 25 <main+0x11> 
    29: 31 c0     xor %eax,%eax 
    2b: c9      leave 
    2c: c3      ret 

Idealmente, profilo (1) e (2) devono essere uguali. Ma vedo che ci sono movl, pushl ecc nell'elenco (1) mentre mov, push in lendo (2). La mia domanda è:

  1. Qual è l'istruzione di assemblaggio corretta effettivamente eseguita sul processore?
  2. In lista (1), vedo questo in principio:

.file "test.c" 
    .globl accum 
     .bss 
     .align 4 
     .type accum, @object 
     .size accum, 4 
    accum: 
     .zero 4 
     .text 
     .p2align 2,,3 
    .globl sum 
     .type sum, @function 

e questo alla fine:

.size main, .-main 
      .section .note.GNU-stack,"",@progbits 
      .ident "GCC: (GNU) 3.4.6 20060404 (Red Hat 3.4.6-9)" 

Cosa significa?

Grazie.

risposta

13

L'istruzione è denominata MOV qualsiasi variante venga utilizzata. Il suffisso l è solo una convenzione di assieme di gcc/AT & T per specificare la dimensione degli operandi desiderati, in questo caso operandi da 4 byte.

In Intel sintassi - dove c'è alcuna ambiguità - invece di suffisso della istruzione è usuale per contrassegnare il parametro di memoria con un indicatore delle dimensioni richieste (ad esempio BYTE, WORD, DWORD, ecc), è solo un altro modo di raggiungere la stessa cosa

89 55 è la corretta sequenza di byte per MOV dal registro 32 bit EBP a 32 bit registro ESP. Non c'è niente di sbagliato in entrambi gli elenchi.


Specifica il file che questo codice assembly è stato generato da:

.file "test.c" 

dice che accum è un simbolo globale (variabile C con collegamento esterno):

.globl accum 

I seguenti bytes deve essere inserito in una sezione bss, questa è una sezione che non occupa spazio nel file oggetto ma viene allocata e azzerata in fase di esecuzione.

 .bss 

allineata sul confine 4 byte:

 .align 4 

'un oggetto (una variabile, non certo codice):

 .type accum, @object 

È quattro byte:

 .size accum, 4 

Qui è dove accum è definito, quattro zero byte.

accum: 
     .zero 4 

Ora passare dalla sezione bss alla sezione di testo che è dove le funzioni sono in genere memorizzati.

 .text 

aggiungere fino a tre byte di padding per assicurarsi che siamo su un 4 byte di confine (2^2):

 .p2align 2,,3 

sum è un simbolo globale ed è una funzione.

.globl sum 
     .type sum, @function 

La dimensione del main è "qui" - "dove main iniziato":

.size main, .-main 

Questi in cui vengono specificate le opzioni di stack gcc specifici. Di solito, è qui che si sceglie di avere uno stack eseguibile (non molto sicuro) o meno (di solito preferito).

 .section .note.GNU-stack,"",@progbits 

identificare la versione del compilatore generato questa montaggio:

 .ident "GCC: (GNU) 3.4.6 20060404 (Red Hat 3.4.6-9)" 
+0

+9,000. Grazie. Il bit sulle opzioni di stack specifici di GCC è stato molto utile. – kevinarpe

0

L'assemblatore Elenco e il profilo disassembler mostrano lo stesso codice, ma utilizza una sintassi diversa. L'aggiunta di -l è la variante della sintassi utilizzata da gcc. Che tu abbia una sintassi diversa negli strumenti (output e disassemblatore del compilatore C) mostra una debolezza della tua catena degli strumenti.

Disassemnbly all'offset 11 in somma: mostra solo alcuni byte immondizia. Il punto di ingresso per la funzione successiva è allineato a 4 byte che dà questo spazio vuoto, riempirlo di spazzatura.

Il gruppo di .statements è definito dalla documentazione dell'assemblatore. Di solito non danno alcun codice eseguibile.

Problemi correlati