¿Usar GCC para producir un ensamblaje legible?
Me preguntaba cómo usar GCC en mi archivo fuente C para volcar una versión mnemotécnica del código de máquina para poder ver en qué se estaba compilando mi código. Puedes hacer esto con Java pero no he podido encontrar la manera con GCC.
Estoy intentando reescribir un método C en ensamblaje y ver cómo lo hace GCC sería de gran ayuda.
Si compila con símbolos de depuración (agregue -g
a su línea de comando GCC, incluso si también está usando -O3
1 ), puede usarlo objdump -S
para producir un desensamblado más legible intercalado con la fuente C.
>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 nombres de símbolos en reubicaciones (como lo veráputs
en lascall
instrucciones a continuación)-R
muestra reubicaciones de enlaces dinámicos/nombres de símbolos (útil en bibliotecas compartidas)-C
exige nombres de símbolos de C++-w
es el modo "ancho": no ajusta en línea los bytes del código de máquina-Mintel
: utilice una sintaxis similar a GAS/binutils MASM.intel_syntax noprefix
en lugar de AT&T-S
: intercalar líneas fuente con desmontaje.
Podrías poner algo como alias disas="objdump -drwCS -Mintel"
en tu ~/.bashrc
. Si no está en x86, o si le gusta la sintaxis de AT&T, omita -Mintel
.
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
Tenga en cuenta que esto no se utiliza -r
, por lo que call rel32=-4
no está anotado con el puts
nombre del símbolo. Y parece un roto call
que salta al medio de la instrucción de llamada en principal. Recuerde que el rel32
desplazamiento en la codificación de la llamada es solo un marcador de posición hasta que el vinculador complete un desplazamiento real (a un código auxiliar PLT en este caso, a menos que vincule estáticamente libc).
Nota al pie 1 : El entrelazado de fuentes puede resultar complicado y no muy útil en compilaciones optimizadas; para eso, considere https://godbolt.org/ u otras formas de visualizar qué instrucciones van con qué líneas fuente. En el código optimizado no siempre hay una única línea fuente que representa una instrucción , pero la información de depuración seleccionará una línea fuente para cada instrucción ASM.
Si le das a GCC la bandera -fverbose-asm
, lo hará.
Coloque información de comentarios adicional en el código ensamblador generado para hacerlo más legible.
[...] Los comentarios agregados incluyen:
- información sobre la versión del compilador y las opciones de la línea de comandos,
- las líneas de código fuente asociadas con las instrucciones de ensamblaje, en el formato NOMBRE DE ARCHIVO: NÚMERO DE LÍNEA: CONTENIDO DE LA LÍNEA,
- sugerencias sobre qué expresiones de alto nivel corresponden a los distintos operandos de instrucciones ensambladoras.
Utilice el interruptor -S (nota: S mayúscula) a GCC y emitirá el código ensamblador a un archivo con una extensión .s. Por ejemplo, el siguiente comando:
gcc -O2 -S foo.c
dejará el código ensamblador generado en el archivo foo.s.
Extraído directamente de http://www.delorie.com/djgpp/v2faq/faq8_20.html (pero eliminando errores -c
)