c++ - sobre - test armado de pc
Preguntas sobre el ensamblaje generado a partir de mi C++ por gcc (3)
Compilando este código:
int main ()
{
return 0;
}
utilizando:
gcc -S filename.cpp
... genera esta asamblea:
.file "heloworld.cpp"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
.cfi_personality 0x0,__gxx_personality_v0
pushl %ebp
.cfi_def_cfa_offset 8
movl %esp, %ebp
.cfi_offset 5, -8
.cfi_def_cfa_register 5
movl $0, %eax
popl %ebp
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
.section .note.GNU-stack,"",@progbits
Mis preguntas:
- Es todo después de "." ¿un comentario?
- ¿Qué es .LFB0 :?
- ¿Qué es .LFE0 :?
- ¿Por qué es un código tan grande solo para "int main ()" y "return 0;"?
PD: leo muchos libros de net de ensamblaje, muchos (al menos 30) de tutoriales y todo lo que puedo hacer es copiar código y pegarlo o reescribirlo. Ahora estoy intentando un enfoque diferente para tratar de aprender de alguna manera. El problema es que entiendo qué son movl, pop, etc., pero no entiendo cómo combinar estas cosas para hacer que el código "fluya". No sé dónde ni cómo comenzar correctamente a escribir un programa en ASM. Todavía estoy estático no dinámico como en C ++, pero quiero aprender a ensamblar.
Como otros han dicho, .file
, .text
, ... son directivas de ensamblador y .LFB0
, .LFE0
son etiquetas locales. La única instrucción en el código generado es:
pushl %ebp
movl %esp, %ebp
movl $0, %eax
popl %ebp
ret
Las primeras dos instrucciones son el prólogo de la función. El puntero de marco se almacena en la pila y se actualiza. El siguiente almacén de instrucciones 0 en el registro eax
(i386 ABI indica que el valor de retorno entero se devuelve a través del registro eax
). Las dos últimas instrucciones son función epílogo. El puntero de marco se restaura y luego la función regresa a su interlocutor a través de la instrucción ret
.
Si compila su código con -O3 -fomit-frame-pointer
, el código se compilará con solo dos instrucciones:
xorl %eax,%eax
ret
El primer conjunto eax
a 0 (solo toma dos bytes codificar, mientras que movl 0,%eax
toma 5 bytes), y el segundo es la instrucción ret
. La manipulación del puntero de marco está ahí para facilitar la depuración (es posible rastrear el camino sin él, pero es más difícil).
Es solo que hay muchas cosas detrás de tu simple programa.
Si tiene la intención de leer salidas de ensamblador, de ninguna manera compile C ++. Use plain C, la salida es mucho más clara por varias razones.
.file
, .text
, etc. son directivas ensambladoras.
.LFB0
, .LFE0
son etiquetas locales, que normalmente se utilizan como destinos de sucursal dentro de una función.
En cuanto al tamaño, en realidad solo hay unas pocas instrucciones reales: la mayoría de las listas anteriores están compuestas por directivas, etc. Para referencia futura, también es posible que desee aumentar el nivel de optimización para eliminar las instrucciones redundantes, es decir, gcc -Wall -O3 -S ...