【问题标题】:C Macro utilizing immediate values in embedded arm asm - armccC 宏利用嵌入式 arm asm 中的立即值 - armcc
【发布时间】:2013-01-31 01:15:10
【问题描述】:

与我的问题最接近的主题是Escaping a # symbol in a #define macro?How to print a pound / hash via C preprocessor?,但它们并不能完全回答我的问题。更明确地说,第二个似乎不适用于 armcc 编译器。它只打印 hash4 而不是 hash 定义的符号。 Chris Lutz 在第二篇文章中特别贬低了尝试使用宏来实现此功能,所以这可能是不正确的方法。不过,我想要更多的想法,而不仅仅是一个人。

问题如下:我正在尝试编写一个使用宏定义嵌入式 asm C 函数的宏。我基本上已经实现了它,除了一个问题......表达了一个直接的价值。立即值的语法需要(我相信)一个磅符号,它也是预处理器的“字符串化”符号。那么,是否可以在 C 宏中转义 # 符号?

这背后的主要目的是用 pico 内核线程上下文管理过程包装一个 isr,并且新过程的函数指针最终将传递给向量中断控制器。

代码如下:

#define ISR_THREAD_MGMT(ISR_FUNC,FUNC_NAME) \
__asm void FUNC_NAME ( void ); \
__asm void FUNC_NAME (void ) \
{ \
    STMDB sp!, {r0-r3}; \
    MRS   r0, SPSR; \
    SUB   lr, lr, #4; \        <----- Heres the problem
    STMDB sp!, {r0, r10, r12, lr}; \
    bl _thread_vectored_context_save; \
    bl ISR_FUNC; \
    b _thread_context_restore; \
}

我希望我已经足够详细地解释了所有内容。如果没有,请不要犹豫,询问更多详细信息。

【问题讨论】:

  • 我的第一直觉是“不要为此使用宏”,但显然你已经看到其他人这么说,所以我不确定你希望我们说什么 - 你是试图使用宏预处理器来做它从未设计过的事情。如果您使用的是 at&t 语法,那么 if 会神奇地工作,因为 $ [indication of constant] 不是预处理器“特殊字符”。一种解决方案当然是在单个函数中实际写出 FUNC_NAME 和 ISR_FUNC - 或者不将 C 编译器用于汇编代码......
  • 总的来说,我想要一个比一个人的想法更大的共识。那么,您是说将嵌入式汇编指令指定为宏超出了其预期用途吗?宏最初不是为内联函数调用而编写的吗?此外,一个不允许您编写所有符号的文本预处理器?对我来说似乎很奇怪......
  • C 预处理器是为 C 设计的——它是它名字的一部分。在设计 C 时,内联汇编器不是范围的一部分——编译器会产生汇编器,然后通过系统汇编器进行汇编——如果你想自己添加汇编代码,你写了一个 something.s 文件——它仍然是有效的选项。大多数汇编程序确实具有宏功能,可让您一遍又一遍地生成相同的代码,但有变体。
  • 是的,我已经通过那个方法实现了它,我只是觉得因为 arm 有一个嵌入式汇编器,所以周围有额外的 asm 文件并不那么简洁。我只是觉得奇怪的是文本预处理器不允许您打印任何字符。为什么你认为限制?在解析器端易于编码?或者他们只是从未见过用例?
  • 嗯,您的用例并不完全是“主流”,是吗?但是请务必联系 ARM 并说“请确保我可以使用您的预处理器使内联汇编器与 # 一起工作” - 他们可能会添加某种扩展。我没有看到操作系统中有“interrupts.s”或类似的东西作为“额外的 asm 文件”——这是我所期望的。 Linux 有它,Symbian OS 有它,据我所知,Windows 和 OSE 一样——还有一个用于 Xerox 的专有操作系统,我不记得它的名称 [但我移植了代码]。

标签: c macros escaping armcc


【解决方案1】:

您引用的第二个问题向您展示了如何做到这一点:

#define hash #
#define mash(x) x
#define immediate(a) mash(hash)a
#define ISR_THREAD_MGMT(ISR_FUNC,FUNC_NAME) \
__asm void FUNC_NAME ( void ); \
__asm void FUNC_NAME ( void ) \
{ \
    STMDB sp!, {r0-r3}; \
    MRS   r0, SPSR; \
    SUB   lr, lr, immediate(4); \
    STMDB sp!, {r0, r10, r12, lr}; \
    bl _thread_vectored_context_save; \
    bl ISR_FUNC; \
    b _thread_context_restore; \
}

ISR_THREAD_MGMT(abc,def)

输出:

# 1 "x.c"
# 1 "<command-line>"
# 1 "x.c"
# 17 "x.c"
__asm void def ( void ); __asm void def ( void ) { STMDB sp!, {r0-r3}; MRS r0, SPSR; SUB lr, lr, #4; STMDB sp!, {r0, r10, r12, lr}; bl _thread_vectored_context_save; bl abc; b _thread_context_restore; }

重新格式化输出:

# 1 "x.c"
# 1 "<command-line>"
# 1 "x.c"
# 17 "x.c"
__asm void def ( void );
__asm void def ( void )
{
    STMDB sp!, {r0-r3};
    MRS r0, SPSR;
    SUB lr, lr, #4;
    STMDB sp!, {r0, r10, r12, lr};
    bl _thread_vectored_context_save;
    bl abc;
    b _thread_context_restore;
}

我不相信这是一个好主意,但至少它确实有效。

【讨论】:

  • 我尝试使用 armcc 编译器无济于事。你在用 gcc 吗?感谢您的回复。
  • 你真的需要immediate(4)吗?也许mash(hash)4 也可以?使用gcc -E ... 的快速测试似乎表明了这一点。
  • 不幸的是,armcc 似乎无法在类似函数的宏中正确解析散列定义。它只是打印参数'hash'
  • 我不知道armcc 在做什么……但我认为它不遵循 C 标准。 @JosephQuinsey:在我看来,符号 immediate(4)mash(hash)4 更容易识别,所以我宁愿使用它——只要相关的 C 预处理器使用它。
  • 如果到那时我还没有解决方案,我想我明天会联系 ARM 代表。他们很可能会说这是不存在的功能,但无论响应如何,我都会随时通知您。谢谢你们的努力,伙计们。
猜你喜欢
  • 2012-06-13
  • 1970-01-01
  • 2023-04-02
  • 1970-01-01
  • 1970-01-01
  • 2013-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多