assembler - ¿Usando GCC para producir ensamblajes legibles?
use assembler in c (9)
Me preguntaba cómo usar GCC en mi archivo fuente C para volcar una versión mnemotécnica del código de la máquina para poder ver en qué se estaba compilando mi código. Puedes hacer esto con Java, pero no he podido encontrar una manera con GCC.
Estoy tratando de volver a escribir un método C en ensamblado y ver cómo GCC lo hace sería una gran ayuda.
Use el conmutador -S (nota: mayúscula S) a GCC, y emitirá el código de ensamblaje a un archivo con la extensión .s. Por ejemplo, el siguiente comando:
gcc -O2 -S foo.c
dejará el código de ensamblaje generado en el archivo foo.s.
Arrancado directamente desde http://www.delorie.com/djgpp/v2faq/faq8_20.html (pero eliminando el error -c
)
¿ gcc -S -fverbose-asm -O source.c
luego gcc -S -fverbose-asm -O source.c
en el archivo ensamblador de source.s
generado?
El código del ensamblador generado va a source.s
(puede anularlo con -o
assembler-filename ); La opción -fverbose-asm
le pide al compilador que emita algunos comentarios del ensamblador "explicando" el código del ensamblador generado. La opción -O
le pide al compilador que optimice un poco (podría optimizar más con -O2
o -O2
).
Si quieres entender qué está haciendo gcc
intenta pasar -fdump-tree-all
pero ten cuidado: obtendrás cientos de archivos de volcado.
Por cierto, GCC es extensible a través de complementos o con MELT (un lenguaje de alto nivel específico del dominio para extender GCC).
El uso del conmutador -S
a GCC en sistemas basados en x86 produce un volcado de la sintaxis de AT&T, de forma predeterminada, que se puede especificar con el -masm=att
, así:
gcc -S -masm=att code.c
Mientras que si deseas producir un volcado en la sintaxis de Intel, puedes usar el -masm=intel
, así:
gcc -S -masm=intel code.c
(Ambos producen volcados de code.c
en su sintaxis, en el archivo code.s
respectivamente)
Para producir efectos similares con objdump, querría usar el --disassembler-options=
intel
/ att
, un ejemplo (con volcados de código para ilustrar las diferencias en la sintaxis):
$ objdump -d --disassembler-options=att code.c
080483c4 <main>:
80483c4: 8d 4c 24 04 lea 0x4(%esp),%ecx
80483c8: 83 e4 f0 and $0xfffffff0,%esp
80483cb: ff 71 fc pushl -0x4(%ecx)
80483ce: 55 push %ebp
80483cf: 89 e5 mov %esp,%ebp
80483d1: 51 push %ecx
80483d2: 83 ec 04 sub $0x4,%esp
80483d5: c7 04 24 b0 84 04 08 movl $0x80484b0,(%esp)
80483dc: e8 13 ff ff ff call 80482f4 <puts@plt>
80483e1: b8 00 00 00 00 mov $0x0,%eax
80483e6: 83 c4 04 add $0x4,%esp
80483e9: 59 pop %ecx
80483ea: 5d pop %ebp
80483eb: 8d 61 fc lea -0x4(%ecx),%esp
80483ee: c3 ret
80483ef: 90 nop
y
$ objdump -d --disassembler-options=intel code.c
080483c4 <main>:
80483c4: 8d 4c 24 04 lea ecx,[esp+0x4]
80483c8: 83 e4 f0 and esp,0xfffffff0
80483cb: ff 71 fc push DWORD PTR [ecx-0x4]
80483ce: 55 push ebp
80483cf: 89 e5 mov ebp,esp
80483d1: 51 push ecx
80483d2: 83 ec 04 sub esp,0x4
80483d5: c7 04 24 b0 84 04 08 mov DWORD PTR [esp],0x80484b0
80483dc: e8 13 ff ff ff call 80482f4 <puts@plt>
80483e1: b8 00 00 00 00 mov eax,0x0
80483e6: 83 c4 04 add esp,0x4
80483e9: 59 pop ecx
80483ea: 5d pop ebp
80483eb: 8d 61 fc lea esp,[ecx-0x4]
80483ee: c3 ret
80483ef: 90 nop
Me gustaría agregar a estas respuestas que si le da a gcc la -fverbose-asm
, el ensamblador que emite será mucho más claro de leer.
No le he dado una inyección a gcc, pero en caso de g ++. El siguiente comando funciona para mí. -g para la compilación de depuración y -Wa, -adhln se pasa al ensamblador para su listado con código fuente
g ++ -g -Wa, -adhln src.cpp
Puedes usar gdb para esto como objdump.
Este extracto se toma de http://sources.redhat.com/gdb/current/onlinedocs/gdb_9.html#SEC64
Aquí hay un ejemplo que muestra una fuente mixta + ensamblaje para Intel x86:
(gdb) disas /m main Dump of assembler code for function main: 5 { 0x08048330 : push %ebp 0x08048331 : mov %esp,%ebp 0x08048333 : sub $0x8,%esp 0x08048336 : and $0xfffffff0,%esp 0x08048339 : sub $0x10,%esp 6 printf ("Hello./n"); 0x0804833c : movl $0x8048440,(%esp) 0x08048343 : call 0x8048284 7 return 0; 8 } 0x08048348 : mov $0x0,%eax 0x0804834d : leave 0x0804834e : ret End of assembler dump.
Use el conmutador -S (nota: mayúscula S) a GCC, y emitirá el código de ensamblaje a un archivo con la extensión .s. Por ejemplo, el siguiente comando:
gcc -O2 -S -c foo.c
gcc.godbolt.org es una herramienta muy útil, ya que solo tienen compiladores de C ++, pero puedes usar el indicador -xc
para tratar el código como C. Luego generará una lista de ensamblados para tu código en paralelo y puedes usar Colourise
Opción para generar barras de colores para indicar visualmente qué código fuente se asigna al ensamblaje generado. Por ejemplo el siguiente código:
#include <stdio.h>
void func()
{
printf( "hello world/n" ) ;
}
usando la siguiente línea de comando:
-x c -std=c99 -O3
y Colourise
generaría lo siguiente:
Si compila con símbolos de depuración, puede usar objdump
para producir un desensamblaje más legible.
>objdump --help
[...]
-S, --source Intermix source code with disassembly
-l, --line-numbers Include line numbers and filenames in output
objdump -drwC -Mintel
es bueno:
-
-r
muestra los nombres de los símbolos en las reubicaciones (para que vea las instrucciones decall
continuación) -
-R
muestra relocalizaciones de enlaces dinámicos / nombres de símbolos (útiles en bibliotecas compartidas) -
-C
desmangle los nombres de los símbolos de C ++ -
-w
es el modo "ancho": no envuelve los bytes del código de la máquina -
-Mintel
: use la sintaxis de.intel_syntax noprefix
GAS / binutils tipo MASM.intel_syntax noprefix
lugar de AT&T -
-S
: entrelazar lineas fuente con desmontaje.
Puedes poner algo como alias disas="objdump -drwCS -Mintel"
en tu ~/.bashrc
Ejemplo:
> gcc -g -c test.c
> objdump -d -M intel -S test.o
test.o: file format elf32-i386
Disassembly of section .text:
00000000 <main>:
#include <stdio.h>
int main(void)
{
0: 55 push ebp
1: 89 e5 mov ebp,esp
3: 83 e4 f0 and esp,0xfffffff0
6: 83 ec 10 sub esp,0x10
puts("test");
9: c7 04 24 00 00 00 00 mov DWORD PTR [esp],0x0
10: e8 fc ff ff ff call 11 <main+0x11>
return 0;
15: b8 00 00 00 00 mov eax,0x0
}
1a: c9 leave
1b: c3 ret