Pregunta

El conjunto de herramientas GCC utiliza AT & T sintaxis de ensamblador de forma predeterminada, pero el soporte para la sintaxis de Intel está disponible a través de la directiva .intel_syntax.

Además, AT & T y la sintaxis de Intel están disponibles en una prefix y una versión noprefix, que difieren en si o no que necesitan para registrar nombres de prefijo con un sigilo %.

Dependiendo de qué directivas están presentes, el formato de dirección de constantes de cambios.

Vamos a considerar el siguiente código C

*(int *)0xdeadbeef = 0x1234;

El uso de objdump -d, nos encontramos con que es compilado a la siguiente instrucción ensamblador

movl $0x1234,0xdeadbeef

Como no hay registros implicados, esto es la sintaxis correcta para ambos .att_syntax prefix y .att_syntax noprefix, es decir. incrustado en el código C, se ven así

__asm__(".att_syntax prefix");
__asm__("movl $0x1234,0xdeadbeef");

__asm__(".att_syntax noprefix");
__asm__("movl $0x1234,0xdeadbeef");

Puede rodear opcionalmente la constante de dirección con paréntesis, es decir.

__asm__("movl $0x1234,(0xdeadbeef)");

funcionará tan bien.

Al añadir un sigilo a una constante dirección de llanura, el código dejará de Copile

__asm__("movl $0x1234,$0xdeadbeef"); // won't compile

Cuando rodea esta expresión con un paréntesis, el compilador emitirá un código incorrecto sin previo aviso, es decir,

__asm__("movl $0x1234,($0xdeadbeef)"); // doesn't warn, but doesn't work!

Esta emitirá incorrectamente la instrucción

movl $0x1234,0x0

En el modo de Intel, una constante de dirección tiene que ser prefijado con un registro de segmento, así como el tamaño del operando y la bandera PTR si ambigüedad es posible. En mi máquina (un ordenador portátil de doble núcleo de Intel con Windows XP y versiones actuales del CCG MinGW y Cygwin), el ds registro se utiliza por defecto.

Los corchetes alrededor de la constante son opcionales. La constante de dirección también se reconoce correctamente si se omite el registro de segmento, pero los soportes están presentes. La omisión del registro emite una advertencia en mi sistema, sin embargo.

En el modo prefix, el registro de segmento tiene que ser precedido de %, pero sólo utilizando soportes seguirá funcionando. Estas son las diferentes maneras de generar la instrucción correcta:

__asm__(".intel_syntax noprefix");
__asm__("mov DWORD PTR ds:0xdeadbeef,0x1234");
__asm__("mov DWORD PTR ds:[0xdeadbeef],0x1234");
__asm__("mov DWORD PTR [0xdeadbeef],0x1234"); // works, but warns!

__asm__(".intel_syntax prefix");
__asm__("mov DWORD PTR %ds:0xdeadbeef,0x1234");
__asm__("mov DWORD PTR %ds:[0xdeadbeef],0x1234");
__asm__("mov DWORD PTR [0xdeadbeef],0x1234"); // works, but warns!

omitir ambas registro de segmento y los soportes fallará para compilar

__asm__("mov DWORD PTR 0xdeadbeef,0x1234"); // won't compile

Yo marcaré esta cuestión como wiki de la comunidad , por lo que si usted tiene algo útil que añadir, no dude en hacerlo.

¿Fue útil?

Solución

Las directivas noprefix / prefix sólo controlan si los registros requieren un prefijo % (*) (al menos lo parece y esa es la única diferencia la documentación menciona). Los literales de valor siempre necesitan un prefijo $ en la sintaxis de AT & T y nunca en la sintaxis de Intel. Por lo tanto, las siguientes obras:

__asm__(".intel_syntax prefix");
__asm__("MOV [DWORD PTR 0xDEADBEEF], 0x1234");

Si está realmente inclinado a usar ensamblador en línea sintaxis de Intel en el código C compilado con GCC y montado con el gas, no se olvide de añadir también lo siguiente después de ella, para que el ensamblador puede asimilar el resto de la (sintaxis AT & T) ensamblado generado por GCC:

__asm__(".att_syntax prefix");

El razonamiento que veo para la distinción prefijo / noprefix es, que la sintaxis de AT & T, el prefijo % no es realmente necesario para los registros en la arquitectura Intel, ya que los registros se nombran. Pero para la uniformidad puede ser allí porque algunas otras arquitecturas (es decir SPARC) han numerados registrado, en cuyo caso la especificación de un número bajo solos serían ambigua en cuanto a si una dirección de memoria o registro estaba destinado.

Otros consejos

Aquí están mis resultados:

*(int *)0xdeadbeaf = 0x1234; // reference implementation

// AT&T: addresses without sigil; parentheses are optional

__asm__(".att_syntax prefix");
__asm__("movl $0x1234,0xdeadbeaf");     // works
__asm__("movl $0x1234,(0xdeadbeaf)");   // works
__asm__("movl $0x1234,($0xdeadbeaf)");  // doesn't work, doesn't warn!
//__asm__("movl $0x1234,$0xdeadbeaf");  // doesn't compile
//__asm__("movl 0x1234,0xdeadbeaf");    // doesn't compile
//__asm__("movl 0x1234,(0xdeadbeaf)");  // doesn't compile

__asm__(".att_syntax noprefix");
// same as above: no registers used!

// Intel: addresses with square brackets or segment register prefix
// brackets without prefix will warn

__asm__(".intel_syntax noprefix");
__asm__("mov DWORD PTR ds:0xdeadbeaf,0x1234");      // works
__asm__("mov DWORD PTR ds:[0xdeadbeaf],0x1234");    // works
__asm__("mov DWORD PTR [0xdeadbeaf],0x1234");       // works, but warns!
//__asm__("mov DWORD PTR 0xdeadbeaf,0x1234");       // doesn't compile

// `prefix` will add % to register names

__asm__(".intel_syntax prefix");
__asm__("mov DWORD PTR %ds:0xdeadbeaf,0x1234");     // works
__asm__("mov DWORD PTR %ds:[0xdeadbeaf],0x1234");   // works
__asm__("mov DWORD PTR [0xdeadbeaf],0x1234");       // works, but warns!
//__asm__("mov DWORD PTR 0xdeadbeaf,0x1234");       // doesn't compile

__asm__(".att_syntax prefix");
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top