sintaxis programas juegos funciones ejemplos dev comandos codigos basicos c debugging assembly gdb

juegos - programas en c++ ejemplos basicos



¿Cómo asociar el código de ensamblaje a la línea exacta en el programa C? (4)

Aquí hay un ejemplo encontrado a través de un sitio web de ensamblaje. Este es el código C:

int main() { int a = 5; int b = a + 6; return 0; }

Aquí está el código ensamblador asociado:

(gdb) disassemble Dump of assembler code for function main: 0x0000000100000f50 <main+0>: push %rbp 0x0000000100000f51 <main+1>: mov %rsp,%rbp 0x0000000100000f54 <main+4>: mov $0x0,%eax 0x0000000100000f59 <main+9>: movl $0x0,-0x4(%rbp) 0x0000000100000f60 <main+16>: movl $0x5,-0x8(%rbp) 0x0000000100000f67 <main+23>: mov -0x8(%rbp),%ecx 0x0000000100000f6a <main+26>: add $0x6,%ecx 0x0000000100000f70 <main+32>: mov %ecx,-0xc(%rbp) 0x0000000100000f73 <main+35>: pop %rbp 0x0000000100000f74 <main+36>: retq End of assembler dump.

Puedo suponer con seguridad que esta línea de código de ensamblado:

0x0000000100000f6a <main+26>: add $0x6,%ecx

correlaciona a esta línea de C:

int b = a + 6;

Pero, ¿hay alguna manera de extraer qué líneas de ensamblaje están asociadas a la línea específica del código C?
En esta pequeña muestra no es demasiado difícil, pero en programas más grandes y al depurar una mayor cantidad de código, resulta un poco engorroso.


Pero, ¿hay alguna manera de extraer qué líneas de ensamblaje están asociadas a la línea específica del código C?

Sí, en principio, tu compilador probablemente pueda hacerlo (opción GCC -fverbose-asm , por ejemplo). Alternativamente, objdump -lSd o similar desensamblará un archivo de programa o objeto con anotaciones de fuente y número de línea donde esté disponible.

Sin embargo, en general, para un programa optimizado grande, esto puede ser muy difícil de seguir.

Incluso con la anotación perfecta, verá la misma línea fuente mencionada varias veces a medida que las expresiones y declaraciones se dividen, intercalan y reordenan, y algunas instrucciones asociadas con múltiples expresiones de origen.

En este caso, solo necesita pensar en la relación entre su fuente y la asamblea, pero requiere un poco de esfuerzo.


@Useless tiene mucha razón. De todos modos, un truco para saber dónde ha llegado C en el código máquina es inyectar marcadores en él; por ejemplo,

#define ASM_MARK do { asm __volatile__("nop; nop; nop;/n/t" :::); } while (0); int main() { int a = 5; ASM_MARK; int b = a + 6; ASM_MARK; return 0; }

Ya verás:

main: pushq %rbp movq %rsp, %rbp movl $5, -4(%rbp) nop; nop; nop; movl -4(%rbp), %eax addl $6, %eax movl %eax, -8(%rbp) nop; nop; nop; movl $0, %eax popq %rbp ret

Necesita usar la palabra clave __volatile__ o equivalente para decirle al compilador que no interfiera y esto es a menudo específico del compilador (observe el __ ), ya que C no proporciona este tipo de sintaxis.


Una de las mejores herramientas que he encontrado para esto es el Explorador de compiladores de Matthew Godbolt.

Cuenta con varias cadenas de herramientas de compilación, recompila automáticamente, e inmediatamente muestra la salida del ensamblaje con líneas de color para mostrar la línea correspondiente de código fuente.


En primer lugar, debe compilar el programa guardando información del archivo de objeto sobre el código fuente, ya sea a través de gdwarf flag o de ambos. A continuación, si desea depurar, es importante que el compilador evite las optimizaciones; de lo contrario, es difícil ver un ensamblado de código de correspondencia <>.

gcc -gdwarf -g3 -O0 prog.c -o out

Luego, dile al desensamblador que emita el código fuente. La bandera de source implica la bandera de disassemble .

objdump --source out