3

我需要编写一个需要内联汇编的宏

#define create_me(name) \
  __asm\
  mov name,#0x1021\
  __endasm\

# 但是没有编译。我尝试将它作为参数传递,但这也不起作用。它说无效的预处理器令牌。我可以尝试使用内联函数,但无法动态创建寄存器名称。那就是我无权访问 name 变量。有没有人对如何在宏中使用 # 操作有任何建议。

我看过在#define 宏中转义# 符号?,但我已经清楚地解释了为什么我需要这里的宏。我的用例不同。

4

4 回答 4

6

通过另一个宏使用间接应该可以解决问题:

#define HASH_LIT #
#define HASH() HASH_LIT

#define create_me(name) \
  __asm\
  mov name,HASH()0x1021\
  __endasm
于 2016-07-07T12:12:30.450 回答
2

对于 SDCC,请使用新__asm__格式。

#define create_me(name) \
      __asm__( "mov "    #name    ", #0x1021" )
于 2016-07-07T12:52:49.057 回答
0

预处理器命令/指令始终以尖号 ( ) 开头#,您不能将其用于您自己的符号。

如果要创建一个名为的变量,请whatever0x1021使用标记串联 ##

#include <stdio.h>

#define create_me(name) name ## 0x121

int main(void)
{
    int create_me(a); /* int a0x121; */

    return 0;
}
于 2016-07-07T12:01:30.840 回答
0

它有助于理解问题的本质。该#符号在三个方面对预处理器来说是特殊的:

  1. 预处理器将其第一个预处理标记的源代码行#识别为不是“文本行”。也就是说,它包含预处理器的指令。另一方面,文本行是要处理的数据——主要是 C 程序源,但可能包含要扩展的宏。#如果它不是行上的第一个预处理标记,则在这个意义上它并不特殊。

  2. 在类函数宏的替换列表的预处理标记中,标记#是字符串化运算符。但是,它不适用于类似变量的宏,也不适用于重新扫描宏扩展文本以进行进一步的宏替换。

  3. 在类函数宏的替换列表的预处理标记中,标记##是标记粘贴运算符。但是,它不适用于类似变量的宏,也不适用于重新扫描宏扩展文本以进行进一步的宏替换。

正如@Quentin 演示的那样,您无法逃避对#预处理器本身的重要性,但是您仍然可以通过使用一些间接来实现所需的宏。首先,如果 a#出现在类似函数的宏的扩展中,那么它不能直接出现在该宏的替换文本中,在那里它将被解释为字符串化运算符。相反,它必须通过扩展另一个宏来引入。其次,如果它必须与其他没有空格的文本相邻,那么扩展到它的直接宏必须是类似函数的宏本身,以便括号用于将宏名称与相邻文本分开。这需要第二级间接。

于 2016-07-07T13:50:05.723 回答