2010-10-26 15 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)" 

Este es un código de montaje generada a partir de este programa C:Analizar código ensamblador

#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; 
} 

Además, este es el código objeto generado desde el programa anterior:

$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, listado (1) y (2) deben ser iguales. Pero veo que hay movl, pushl, etc. en el listado (1) mientras que mov, ingresa lising (2). Mi pregunta es:

  1. ¿Cuál es la instrucción de ensamblaje correcta realmente ejecutada en el procesador?
  2. en el listado (1), veo esto en el 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 

y esto al final:

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

¿Qué significa esto?

Gracias.

Respuesta

13

La instrucción se llama MOV sea cual sea la variante que se esté utilizando. El sufijo l es simplemente una convención de ensamblaje de gcc/AT & T para especificar el tamaño de los operandos deseados, en este caso, operandos de 4 bytes.

En la sintaxis de Intel - donde hay alguna ambigüedad - en lugar de como sufijo la instrucción es habitual para marcar el parámetro de memoria con un indicador del tamaño requerido (por ejemplo BYTE, WORD, DWORD, etc.), es sólo otra manera de lograr lo mismo.

89 55 es la secuencia correcta de bytes para MOV desde el registro de 32 bits EBP a la 32-bit de registro ESP. No hay nada de malo en ninguno de los listados.


Especifica el archivo que se generó este código de montaje a partir de:

.file "test.c" 

dice que accum es un símbolo global (variable C con enlace externo):

.globl accum 

Los siguientes bytes debe colocarse en una sección bss, esta es una sección que no ocupa espacio en el archivo objeto, pero se asigna y se pone a cero en el tiempo de ejecución.

 .bss 

alineados en un límite de 4 bytes:

 .align 4 

trata de un objeto (una variable, no un código):

 .type accum, @object 

Es cuatro bytes:

 .size accum, 4 

Aquí es donde accum es definido, cuatro bytes cero.

accum: 
     .zero 4 

Ahora interruptor de la sección bss a la sección de texto que es donde se suelen almacenar funciones.

 .text 

añadir hasta tres bytes de relleno para hacer límite seguro de que estamos en un byte 4 (2^2):

 .p2align 2,,3 

sum es un símbolo global y es una función.

.globl sum 
     .type sum, @function 

El tamaño de main es "aquí" - "donde comenzó main":

.size main, .-main 

Estos donde se especifican las opciones de pila gcc específicos. Usualmente, aquí es donde eliges tener una pila ejecutable (no muy segura) o no (generalmente preferida).

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

identificar la versión del compilador genera este montaje:

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

+9,000. Gracias. El poco sobre las opciones de pila específicas de GCC fue muy útil. – kevinarpe

0

El ensamblador lista y el listado de desensamblador muestran el mismo código, pero el uso de una sintaxis diferente. El apilado -l es la variante de sintaxis utilizada por gcc. Que tenga una sintaxis diferente en las herramientas (salida y desensamblador del compilador C) muestra una debilidad de su cadena de herramientas.

Desasonablemente en offset 11 en suma: muestra solo algunos bytes basura. El punto de entrada a la siguiente función principal está alineado a 4 bytes, lo que le da a este espacio, lo llena de basura.

El conjunto de .estados se define por la documentación del ensamblador. Por lo general, no dan ningún código ejecutable.

Cuestiones relacionadas