La RealView BRAZO Compilador de C soporta la colocación de una variable en una determinada dirección de memoria usando el atributo variable at(address):

int var __attribute__((at(0x40001000)));
var = 4;   //changes the memory located at 0x40001000

Hace GCC tiene una similar atributo variable?

  • Escribí un artículo, donde puedo enumerar los medios para hacerlo. Podría ser útil para algunos.
InformationsquelleAutor Bas van Dijk | 2010-11-01

5 Comentarios

  1. 21

    No sé, pero usted puede crear fácilmente una solución como esta:

    int *var = (int*)0x40001000;
    *var = 4;

    No exactamente la misma cosa, pero en la mayoría de las situaciones un sustituto perfecto. Se trabajará con cualquier compilador, no sólo GCC.

    Si utiliza GCC, supongo que también uso GNU ld (aunque no es una certeza, por supuesto) y ld tiene soporte para la colocación de las variables dondequiera que usted quiere que ellos.

    Me imagino dejando que el enlazador hacer ese trabajo es bastante común.

    Inspirado por la respuesta @costilla, voy a agregar que si la dirección absoluta de registro de control, me gustaría añadir volatile para el puntero de la definición. Si se trata sólo de RAM, no importa.

    • +1 para la creatividad. No sé si realmente funciona, pero suena muy plausible, así como portátil (en el sentido de que se debe trabajar para todos los compiladores).
    • Es bastante estándar, un truco utilizable en los controladores de dispositivo de hardware fijo asignados a la memoria los registros de control.En una aplicación de usuario estándar, que no tiene ninguna utilidad todo lo que puedo pensar.
    • en dispositivos embebidos, especialmente aquellos que no MMU, es muy común que el «aplicaciones de usuario» golpear en el hardware.
    • Clark Kant: De Acuerdo. Por «aplicación de usuario estándar» yo en realidad quería decir aquellos que se ejecutan en modernas de las computadoras de propósito general en el espacio de usuario.
    • eso fue más o menos mi punto de vista, la cuestión no indicar si la memoria es accesible de esta manera, o si usted necesita el compilador para tomar ciertas acciones para hacer que suceda.
    • sí, me imaginé. Simplemente no puedo dejar ir de las veces cuando un «moderno equipo de propósito general» fue un Amiga 500. 🙂 (Pero, incluso entonces, la escritura a direcciones absolutas estaba muy mal visto.)
    • No estoy seguro de lo que quieres decir con «muy a menudo». En muchos dispositivos embebidos, si «las aplicaciones de usuario» no podía golpear el hardware, nada nunca. Mientras que la definición de nombres simbólicos para las direcciones es útil en general, y sería muy útil para los compiladores para proporcionar una opción para interpretar lvalues de entero-a-puntero arroja como implícitamente que requieren volátil de acceso (ya que por cualquiera que sea la razón por la que muchos proveedores de chips incluir archivos de cabecera que el abandono de la volatilidad del calificador), no estoy seguro de lo que te gustaría ver diferentes.
    • No me refiero exactamente igual. Estoy de acuerdo con usted. Me refería a algo más parecido a «por desgracia, no hemos llegado tan lejos como acabar con la programación de bajo nivel». Es más, como es el aumento, cada vez con mayor programación embebida en todo. Pero no es que no me quejo, me gusta bastante embebidos y sistemas de programación. 🙂 Pero aún así, creo que los nombres simbólicos pueden ser útiles. El Amiga OS, incluso había «tiempo de ejecución» de direcciones simbólicas. Usted podría leer de la dirección de $4, que contiene un puntero a un salto de la tabla de llamadas al sistema. Incluso sin MMU, usted no tiene que depender de direcciones fijas para que OS llama. Estoy divagando
    • Yo creo que ciertas cosas son lamentables; compiladores utilizados para exponer que subyacen el comportamiento del hardware para la mayoría de las formas de la UB, mientras que hoy en día hay más de una tendencia a hacer de la UB basado en «optimizaciones». Solía ser que (x<<n) | (x>>(32-n)) fue canónica de la manera de hacer un «girar a la izquierda», y es utilizado para trabajar en el 99,999% de las plataformas donde x puede ser un entero de 32-bit (tipo no conozco excepciones que las configuran excepcionalmente-pedante modo), pero de hoy en día, los compiladores examinar que la expresión y deducir que x no puede ser cero. Hubo históricamente, sólo…
    • …dos maneras de procesadores habría manejado x>>32, y cualquiera de ellos hubiera funcionado igual de bien en esa expresión. Dado que la norma considera UB, sin embargo, algunos programadores de compiladores no veo ninguna razón para exponer que subyacen el comportamiento del hardware.
    • Me gustaría cambiar el tipo de puntero a int *const, por lo que el compilador puede optimizar la eliminación de referencias de distancia.
    • La punta de objeto debe ser casi siempre declarado volátiles para que esto sea de alguna manera útil, de lo Contrario, ¿por qué iba a importar de donde reside en la memoria.
    • Vamos a asumir que es una variable global en una dirección conocida. Podría todavía se almacena en la caché caché de CPU con ningún efecto perjudicial. Sin embargo, si la dirección representa la memoria de e/S asignada, entonces el valor se puede cambiar desde «bajo sus pies» por eventos externos. A continuación, volátil, es muy útil. O estoy completamente ausente el punto?
    • Mi punto es que si no importa si las lecturas y escrituras se han optimizado, entonces poco importa donde en la memoria reside el objeto – dejar que el compilador decide.
    • por lo general, sí. Pero en Amiga de Kickstart, la dirección fue de $4, si te gustó o no. Y sé sistemas embebidos con direcciones fijas el uso compartido de las variables globales.

  2. 15

    Podría utilizar el la sección atributos y un ld linker script para definir la dirección deseada para esa sección. Esta es probablemente la más complicada de lo de sus alternativas, pero es una opción.

    • Tenga en cuenta que este enfoque se en realidad se reserva espacio para la variable, en lugar de simplemente asumir que existe en la dirección especificada. En muchos casos, esto es lo que usted desea.
    • Un vínculo más directo para la sección de atributos: gcc.gnu.org/onlinedocs/gcc/… y la tecla ctrl+f «de la sección»
    • Por desgracia, a veces las herramientas de intentar hacer las cosas de forma más sencilla, ocultar/auto-generando el linker script de modo que es difícil de modificar (te estoy mirando a ti Arduino y ATMEL Studio). Yo sería fantástico encontrar una forma de anclar una variable a una dirección fija y tienen que asignar el espacio en un tramo existente utilizando sólo el código. :/
    • Me han proporcionado un mínimo de ejecutables linker script de ejemplo en: stackoverflow.com/questions/4067811/…
  3. 7

    Que responde a tu pregunta
    En el enlace de arriba que dice:

    Con el Compilador GNU GCC solo se puede usar definiciones de puntero para acceder absoluta de los lugares de la memoria. Por ejemplo:

    #define IOPIN0         (*((volatile unsigned long *) 0xE0028000))
    IOPIN0 = 0x4;

    Btw http://gcc.gnu.org/onlinedocs/gcc-4.5.0/gcc/Variable-Attributes.html#Variable%20Attributes

    • Interesante, no sabía de que.
    • de hecho, con este enfoque no se limita a sólo una variable. Usted puede hacer esto también con los punteros a estructuras, que representan a todo el conjunto de registros para un determinado periférico
  4. 4
        extern const uint8_t dev_serial[12];
        asm(".equ dev_serial, 0x1FFFF7E8");
    /* or    asm("dev_serial = 0x1FFFF7E8"); */
        ...
    
        for (i = 0 ; i < sizeof(dev_serial); i++)
            printf((char *)"%02x ", dev_serial[i]);
    • Lo que hace este complemento a las respuestas existentes?
    • Mientras este fragmento de código se puede resolver la cuestión, , incluyendo una explicación de realmente ayuda a mejorar la calidad de tu post. Recuerde que usted está respondiendo a la pregunta para los lectores en el futuro, y esas personas pueden no saber las razones de su sugerencia de código. Por favor trate de no entrar en su código con comentarios explicativos, esto reduce la legibilidad del código y las explicaciones!
    • Esta realidad hay que añadir algo que las otras respuestas no. Con este enfoque se puede cambiar la posición de una longitud fija de la matriz, mientras que todavía permite sizeof() para obtener el tamaño de la matriz.
  5. 4

    Mínima de ejecutables linker script de ejemplo

    La técnica se mencionó en: https://stackoverflow.com/a/4081574/895245 pero ahora, ahora voy a ofrecer un ejemplo concreto.

    principal.c

    #include <stdio.h>
    
    int __attribute__((section(".mySection"))) myvar = 0x9ABCDEF0;
    
    int main(void) {
        printf("adr %p\n", (void*)&myvar);
        printf("val 0x%x\n", myvar);
        myvar = 0;
        printf("val 0x%x\n", myvar);
        return 0;
    }

    link.ld

    SECTIONS
    {
      .mySegment 0x12345678 : {KEEP(*(.mySection))}
    }

    GitHub aguas arriba.

    Compilar y ejecutar:

    gcc -fno-pie -no-pie -o main.out -std=c99 -Wall -Wextra -pedantic link.ld main.c
    ./main.out

    De salida:

    adr 0x12345678
    val 0x9abcdef0
    val 0x0

    Así vemos que se trata de poner en la dirección deseada.

    No puedo encontrar donde esto está documentado en el manual de GCC, pero la siguiente sintaxis:

    gcc link.ld main.c

    parece anexar el dado linker script a la predeterminada que se utiliza.

    -fno-pie -no-pie es necesario, porque el Ubuntu conjunto de herramientas está ahora configurado para generar el PASTEL de los ejecutables de forma predeterminada, el cual lleva el kernel de Linux para colocar el ejecutable en una dirección diferente cada vez, que se mete con nuestro experimento. Ver también: ¿Cuál es la fPIE opción para los ejecutables de posición independiente en el gcc y ld?

    TODO: la compilación genera una advertencia:

    /usr/bin/x86_64-linux-gnu-ld: warning: link.ld contains output sections; did you forget -T?

    Estoy haciendo algo mal? Cómo deshacerse de él? Ver también: Cómo quitar advertencia: enlace.res contiene secciones de salida; ¿has olvidado -T?

    Probado en Ubuntu 18.10, GCC 8.2.0.

Dejar respuesta

Please enter your comment!
Please enter your name here