2010-08-28 15 views
5

Ejemplo:¿Qué es r() y el doble por ciento %% en el lenguaje ensamblador en línea de GCC?

int main(void) 
{ 
    int x = 10, y; 

    asm ("movl %1, %%eax;" 
     "movl %%eax, %0;" 
     :"=r"(y) /* y is output operand */ 
     :"r"(x)  /* x is input operand */ 
     :"%eax"); /* %eax is clobbered register */ 
} 
  • lo que es r(y)?
  • también ¿por qué %% se utiliza antes de eax? En general, solo % se usa ¿verdad?
+0

Además, ¿no obtuve what = r (y) yr (x)? también, ¿qué es un registro destrozado? – brett

+0

Dos porciento doble: http://stackoverflow.com/questions/14745631/what-does-a-double-percent-sign-do-in-gcc-inline-assembly –

+0

Tenga cuidado con el asm básico frente al extendido: http: // stackoverflow.com/a/31711138/895245 –

Respuesta

4

Bien, este es un ensamblador en línea gcc muy poderoso pero difícil de entender.

Primero, el% carbonero es un char especial. Le permite definir los marcadores de posición de registro y número (más adelante, mor). Desafortunadamente, el% también se utiliza como parte de un nombre de registro (como% EAX), por lo que en el ensamblador en línea de gcc debe usar dos por ciento de caracteres si desea nombrar un registro.

% 0,% 1 y% 2 (ect ..) son operandos de entrada y salida de marcador de posición. Estos se definen en la lista seguida de la cadena del ensamblador. En su ejemplo% 0 se convierte en un marcador de posición para y, y% 1 se convierte en un marcador de posición para x. El compilador se asegurará de que las variables estén en los registros para los operandos de entrada antes de que se ejecute el código asm, y se asegurará de que el operando de salida se escriba en la variable especificada en la lista de operandos de salida.

Ahora debe hacerse una idea de lo que es r (y): es un operando de entrada que reserva un registro para la variable y y lo asigna al marcador de posición% 1 (porque es el segundo operando enumerado después del ensamblador en línea cuerda). Hay muchos otros tipos de marcadores de posición. m le permite especificar una ubicación de memoria, y si no me equivoco, puedo usarla para constantes numéricas. Los encontrará todos listados en la documentación de gcc.

Luego está la lista de clobber. ¡Esta lista es importante! Enumera todos los registros, indicadores, etc. de las ubicaciones de memoria que se modifican en su código de ensamblador (como el EAX en su ejemplo). Si obtiene esto mal, el optimizador no sabe qué se ha modificado y es muy probable que termine con un código que no funciona.

Su ejemplo es, por cierto, casi inútil. Simplemente carga el valor X en un registro y asigna este registro a EAX. Luego EAX se almacena en otro registro que luego se convertirá en su variable y.Entonces todo lo que hace es una simple asignación:

y = x;

Una última cosa: si ha trabajado antes con el ensamblador tipo Intel: debe leer los argumentos al revés. Para todas las instrucciones, el operando fuente es el que sigue la instrucción en sí, y el operando objetivo es el que se encuentra a la derecha de la coma. En comparación con la sintaxis de Intel, esto es exactamente al revés.

0

No puedo responder a todo esto, pero un registro mutilado es uno que se utilizará en algún lugar del cálculo de una manera que destruirá su valor actual. Entonces, si la persona que llama quiere usar el valor actual más tarde, necesita guardarlo de alguna manera.

En asm directivas como esta, cuando escribe el conjunto, averigua qué registros van a ser destruidos por él; luego le dice esto al compilador (como se muestra en su ejemplo), y el compilador hace lo que tiene que hacer para preservar el valor actual de ese registro si es necesario. El compilador sabe mucho sobre cómo se usarán los valores en los registros y en otros lugares para cálculos posteriores, pero generalmente no puede analizar el ensamblado integrado. Por lo tanto, usted mismo realiza el análisis y el compilador utiliza la información de trituración para incorporar de forma segura el conjunto en sus opciones de optimización.

0

Pruebe this tutorial. Cubre todo lo que pida: por ejemplo, intente section 6; explica bastante bien las restricciones y para qué sirve el signo "=". Incluso el concepto de registros triturados está cubierto (sección 5.3).

+0

El ejemplo del código en esta pregunta parece ser el tercer ejemplo de la sección 5 de ese tutorial ... :-) –

+0

@Laurence Si el OP está usando ese tutorial, esta pregunta simplemente indica que él/ella aún no ha leído el tutorial completo, ya que cada punto se responde en el tutorial. –

1

Las líneas con "r" o "= r" son restricciones de operandos. El "=" significa operando de salida. Esencialmente, esto:

:"=r"(y) 
:"r"(x) 

significa que% 0 (es decir: el primer operando) corresponde a Y y es para la salida, y el% 1 (el segundo operando) corresponde a x.

Un único% se usa normalmente en AT & conjunto de sintaxis T, pero para el ensamblaje en línea, el% se usa para referencias de operandos (por ej .:% 0,% 1) mientras que un% doble se usa para referencias de registro literales. Piense en la forma en que tiene que usar un doble% en formato de impresión si quiere un% literal en la salida.

Un registro mutilado es un registro cuyo valor será modificado por el código de ensamblaje. Como puede ver en el código, eax está escrito en. Debes informarle a gcc sobre esto para que sepa que el código compilado no puede guardar nada más adelante en eax cuando esté a punto de invocar este ensamblado.

Cuestiones relacionadas