C宏 - 如何将整数值转换为字符串文字

Wos*_*ame 31 c assembly gcc avr c-preprocessor

是否可以将#defined 整数符号的值逐字插入到作为GCC(AVR Studio)中汇编部分一部分的字符串文字中?

我希望在下面的asm()块内的字符串文字中将"LEDS"替换为48.

#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
...
}
Run Code Online (Sandbox Code Playgroud)

但我希望编译器/汇编程序(在预处理器完成它的工作之后)看到这个......

#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
...
}
Run Code Online (Sandbox Code Playgroud)

到目前为止,我已经尝试了所有我能想到的宏观技巧(#stringification,arg替换,甚至包含各种值和双引号组合的#including文件等等).

我完全不熟悉将AVR汇编代码内联到AVR Studio的GCC编译器中的魔力.

我试图避免在我的源代码中多次出现"48"文字,如果预处理器可以为我执行这个替换会很好.

编辑:这是一个微控制器固件项目 - 只是为了让生活变得有趣,几乎没有空间可以添加新代码.

PSk*_*cik 46

我认为在utils头文件中有一个字符串化的宏是很好的:

#define STR_IMPL_(x) #x      //stringify argument
#define STR(x) STR_IMPL_(x)  //indirection to expand argument macros
Run Code Online (Sandbox Code Playgroud)

然后你可以保持宏的数字并在现场将其字符串化:

#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"
...
}
Run Code Online (Sandbox Code Playgroud)

以上预处理:

int x = 48;

void DrawFrame()
{
    asm(
    "ldi        R27, 0x00       \n\t"
    "ldi        R26, 0x00       \n\t"
    "ldi        R18, ""48""       \n\t"
...
}
Run Code Online (Sandbox Code Playgroud)

这取决于相邻字符串文字被连接的事实.

  • 这是我的答案的更好的版本.Upvoted. (4认同)

Jes*_*ter 14

如果使用约束,则可以避免字符串化宏乱:

#define LEDS 48

void DrawFrame()
{
    asm volatile(
    "ldi R18, %[leds]"
    : : [leds] "M" (LEDS) : "r18");
}
Run Code Online (Sandbox Code Playgroud)

  • @Wossname:你如何使用"基本"asm(没有约束)而不踩到编译器的脚趾(即没有告诉它就破坏寄存器)?有关详细信息,请参阅[inline assembly tag wiki](http://stackoverflow.com/tags/inline-assembly/info)."扩展"asm是使用它的常用方法,而AFAIK是唯一安全的方法,不仅仅使用不影响寄存器的指令(例如内存栅栏或其他东西). (2认同)

dbu*_*ush 13

您需要两个辅助宏才能工作.然后你可以利用自动字符串连接:

#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"
...
}
Run Code Online (Sandbox Code Playgroud)

使用两个宏的原因是第一个单独不会扩展传入的参数.

如果你这样做:

printf("LEDS = " STR(LEDS) "\n");
Run Code Online (Sandbox Code Playgroud)

它会扩展到这个:

printf("LEDS = " "LEDS" "\n");
Run Code Online (Sandbox Code Playgroud)

EXPAND宏允许传递的参数中,以及取代.

那么这个:

printf("LEDS = " EXPAND(LEDS) "\n");
Run Code Online (Sandbox Code Playgroud)

将扩展到这个:

printf("LEDS = " "48" "\n");
Run Code Online (Sandbox Code Playgroud)