Trabajo de asm volátil (memoria"":::"")


¿Qué hace básicamente __asm__ __volatile__ () y cuál es el significado de "memory" para la arquitectura ARM?

Author: Tor Klingberg, 2013-02-19

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 ).

 57
Author: auselen,
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.

 17
Author: unixsmurf,
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.

 9
Author: Udo Klein,
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;
}
 -1
Author: leesagacious,
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