Etiquetas en ensamblaje en línea GCC


En mi experimentación continua con el ensamblaje inline de GCC, me he encontrado con un nuevo problema con respecto a las etiquetas y el código inlineado.

Considere el siguiente simple salto:

__asm__
(
    "jmp out;"
    "out:;"
    :
    :
);

Esto no hace nada excepto saltar a la etiqueta out. Como es, este código compila bien. Pero si lo coloca dentro de una función, y luego compila con indicadores de optimización, el compilador se queja: "Error: el símbolo 'out' ya está definido".

Lo que parece estar sucediendo es que el compilador está repitiendo este código de ensamblaje cada vez que alinea la función. Esto hace que la etiqueta out se duplique, dando lugar a múltiples etiquetas out.

Entonces, ¿cómo trabajo alrededor de esto? ¿Realmente no es posible usar etiquetas en el ensamblaje en línea? Este tutorial sobre el ensamblaje inline de GCC menciona que:

Así, usted puede hacer poner su asamblea en macros CPP, y en línea C funciones, por lo que cualquier persona puede usarlo como cualquier función / macro de C. Funciones en línea se asemejan a macros muy mucho, pero son a veces más limpio de usar. Cuidado con eso en todos esos casos, el código será duplicados, por lo que solo etiquetas locales (de 1: estilo) debe definirse en que código asm.

Traté de encontrar más información sobre estas "etiquetas locales", pero parece que no puedo encontrar nada relacionado con el ensamblaje en línea. Parece que el tutorial está diciendo que una etiqueta local es un número seguido de dos puntos, (como 1:), así que intenté usar una etiqueta como esa. Curiosamente, el código compilado, pero en tiempo de ejecución simplemente desencadenó un Error de Segmentación. Hmm...

Así que cualquier sugerencia, sugerencia, respuesta...?

Author: Channel72, 2010-10-10

2 answers

Una declaración de una etiqueta local es de hecho un número seguido de dos puntos. Pero una referencia a una etiqueta local necesita un sufijo de f o b, dependiendo de si desea mirar hacia adelante o hacia atrás, es decir, 1f se refiere a la siguiente etiqueta 1: en la dirección hacia adelante.

Así que declarar la etiqueta como 1: es correcto; pero para referenciarla, necesitas decir jmp 1f (porque estás saltando hacia adelante en este caso).

 45
Author: Matthew Slattery,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-10 00:24:19

Bueno, esta pregunta no se está volviendo más joven, pero hay otras dos soluciones interesantes.

1) Este ejemplo utiliza %=. % = en una plantilla de ensamblador se reemplaza con un número que es "único para cada insn en toda la compilación. Esto es útil para hacer etiquetas locales a las que se hace referencia más de una vez en un insn dado."Tenga en cuenta que para usar%=, (aparentemente) debe tener al menos una entrada (aunque probablemente no tenga que usarla realmente).

int a = 3;
asm (
    "test %0\n\t"
    "jnz to_here%=\n\t"
    "jz to_there%=\n\t"
    "to_here%=:\n\t"
    "to_there%=:"
    ::"r" (a));

Esto salidas:

test %eax
jnz to_here14
jz to_there14
to_here14:
to_there14:

Alternativamente, se puede utilizar el asm goto (Añadido en v4.5 creo). Esto en realidad le permite saltar a etiquetas c en lugar de solo etiquetas asm:

asm goto ("jmp %l0\n"
 : /* no output */
 : /* no input */
 : /* no clobber */
 : gofurther);

printf("Didn't jump\n");

// c label:
gofurther:
printf("Jumped\n");
 25
Author: David Wohlferd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-19 01:24:51