c gcc assembly c-preprocessor avr

C Macro: cómo obtener un valor entero en un literal de cadena



gcc assembly (3)

Esta pregunta ya tiene una respuesta aquí:

¿Es posible obtener el valor de un símbolo entero #defined insertándose textualmente en un literal de cadena que es parte de una sección de ensamblaje en GCC (AVR Studio)?

Quiero que el "LEDS" sea reemplazado por 48 dentro de la cadena literal dentro del bloque asm () a continuación.

#define LEDS 48 //I only want ONE mention of this number in the source int x = LEDS; //I''m using the value directly too void DrawFrame() { asm( "ldi R27, 0x00 /n/t" "ldi R26, 0x00 /n/t" "ldi R18, LEDS /n/t" //<-- substitution needed here ... }

Pero quiero que el compilador / ensamblador (después de que el preprocesador haya hecho su trabajo) vea esto ...

#define LEDS 48 //I only want ONE mention of this number in the source int x = LEDS; //I''m using the value directly too void DrawFrame() { asm( "ldi R27, 0x00 /n/t" "ldi R26, 0x00 /n/t" "ldi R18, 48 /n/t" //<-- substitution needed here ... }

Hasta ahora he intentado con todos los macro tricks en los que puedo pensar (#stringification, arg substitution e incluso #incluyendo archivos con varias combinaciones de valores y comillas dobles y demás).

No estoy nada familiarizado con la magia de incorporar el código ensamblador AVR en el compilador GCC de AVR Studio.

Estoy tratando de evitar tener múltiples apariciones del literal "48" en mi fuente, si el preprocesador puede realizar esta sustitución para mí, sería genial.

Editar: Esto es para un proyecto de firmware de microcontrolador, y para hacer la vida más interesante, casi no hay espacio libre para agregar código nuevo.


Creo que es bueno tener una macro de stringifying en tu encabezado utils:

#define STR_IMPL_(x) #x //stringify argument #define STR(x) STR_IMPL_(x) //indirection to expand argument macros

Luego puede mantener el macro numérico y colocarlo en el lugar:

#define LEDS 48 int x = LEDS; void DrawFrame() { asm( "ldi R27, 0x00 /n/t" "ldi R26, 0x00 /n/t" "ldi R18, "STR(LEDS)" /n/t" ... }

Los preprocesos anteriores para:

int x = 48; void DrawFrame() { asm( "ldi R27, 0x00 /n/t" "ldi R26, 0x00 /n/t" "ldi R18, ""48"" /n/t" ... }

que se basa en el hecho de que los literales de cadena adyacentes se concatenan.


Necesitas dos macros auxiliares para que esto funcione. Entonces puede aprovechar la concatenación automática de cadenas:

#define STR(x) #x #define EXPAND(x) STR(x) #define LEDS 48 int x = LEDS; void DrawFrame() { asm( "ldi R27, 0x00 /n/t" "ldi R26, 0x00 /n/t" "ldi R18, " EXPAND(LEDS) " /n/t" ... }

El motivo para utilizar dos macros es que el primero solo no ampliará el parámetro pasado.

Si acabas de hacer esto:

printf("LEDS = " STR(LEDS) "/n");

Se expandiría a esto:

printf("LEDS = " "LEDS" "/n");

La macro EXPAND permite que el parámetro pasado también sea sustituido.

Entonces esto:

printf("LEDS = " EXPAND(LEDS) "/n");

Se expandiría a esto:

printf("LEDS = " "48" "/n");


Puede evitar el desorden macro de stringification si usa una restricción:

#define LEDS 48 void DrawFrame() { asm volatile( "ldi R18, %[leds]" : : [leds] "M" (LEDS) : "r18"); }