Trabajo de asm volátil (memoria"":::"")
¿Qué hace básicamente __asm__ __volatile__ ()
y cuál es el significado de "memory"
para la arquitectura ARM?
4 answers
asm volatile("" ::: "memory");
Crea una barrera de memoria a nivel de compilador que obliga al optimizador a no reordenar los accesos de memoria a través de la barrera.
Por ejemplo, si necesita acceder a alguna dirección en un orden específico (probablemente porque ese área de memoria está respaldada por un dispositivo diferente en lugar de una memoria), debe poder decirle esto al compilador, de lo contrario, puede optimizar sus pasos en aras de la eficiencia.
Suponga que en este escenario debe incrementar un valor en la dirección, lee algo e incrementa otro valor en una dirección adyacente.
int c(int *d, int *e) {
int r;
d[0] += 1;
r = e[0];
d[1] += 1;
return r;
}
El problema es que el compilador (gcc
en este caso) puede reorganizar el acceso a la memoria para obtener un mejor rendimiento si lo solicita (-O
). Probablemente conduce a una secuencia de instrucciones como la siguiente:
00000000 <c>:
0: 4603 mov r3, r0
2: c805 ldmia r0, {r0, r2}
4: 3001 adds r0, #1
6: 3201 adds r2, #1
8: 6018 str r0, [r3, #0]
a: 6808 ldr r0, [r1, #0]
c: 605a str r2, [r3, #4]
e: 4770 bx lr
Los valores anteriores para d[0]
y d[1]
se cargan al mismo tiempo. Supongamos que esto es algo que desea evitar, entonces necesita decirle al compilador que no reordene los accesos a la memoria y eso es usar asm volatile("" ::: "memory")
.
int c(int *d, int *e) {
int r;
d[0] += 1;
r = e[0];
asm volatile("" ::: "memory");
d[1] += 1;
return r;
}
Así que obtendrá su secuencia de instrucciones como desea que sea:
00000000 <c>:
0: 6802 ldr r2, [r0, #0]
2: 4603 mov r3, r0
4: 3201 adds r2, #1
6: 6002 str r2, [r0, #0]
8: 6808 ldr r0, [r1, #0]
a: 685a ldr r2, [r3, #4]
c: 3201 adds r2, #1
e: 605a str r2, [r3, #4]
10: 4770 bx lr
12: bf00 nop
Debe tenerse en cuenta que esto es solo una barrera de memoria en el tiempo de compilación para evitar que el compilador reordene los accesos a la memoria, ya que no pone instrucciones de nivel de hardware adicionales para vaciar las memorias o esperar a que se complete la carga o los almacenes. Las CPU todavía pueden reordenar los accesos de memoria si tienen las capacidades arquitectónicas y las direcciones de memoria están en el tipo normal
en lugar de strongly ordered
o device
(ref ).
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
2014-03-31 12:45:23
Esta secuencia es una barrera de programación de acceso a memoria del compilador, como se indica en el artículo referenciado por Udo. Este es específico de GCC - otros compiladores tienen otras formas de describirlos, algunos de ellos con declaraciones más explícitas (y menos esotéricas).
__asm__
es una extensión gcc de permitir que se introduzcan instrucciones en lenguaje ensamblador anidadas dentro de su código C-se utiliza aquí por su propiedad de poder especificar efectos secundarios que impiden que el compilador realice ciertos tipos de optimizaciones (que en este caso podrían terminar generando código incorrecto).
__volatile__
se requiere para garantizar que la propia declaraciónasm no se reordene con ningún otro acceso volátil (una garantía en el lenguaje C).
memory
es una instrucción para GCC que (una especie de) dice que la secuencia asm en línea tiene efectos secundarios en la memoria global, y por lo tanto no solo los efectos en las variables locales deben tenerse en cuenta.
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-02-19 07:53:06
El significado se explica aquí:
Http://en.wikipedia.org/wiki/Memory_ordering
Básicamente implica que el código ensamblador se ejecutará donde se espera. Le dice al compilador que no reordene las instrucciones a su alrededor. Eso es lo que se codifica antes de que esta pieza de código se ejecute antes y lo que se codifica después se ejecutará después.
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-02-19 07:17:05
static inline unsigned long arch_local_irq_save(void)
{
unsigned long flags;
asm volatile(
" mrs %0, cpsr @ arch_local_irq_save\n"
" cpsid i" //disabled irq
: "=r" (flags) : : "memory", "cc");
return flags;
}
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
2016-10-26 04:16:04