【问题标题】:gcc arm __asm inline passing constant in parametergcc arm __asm 内联在参数中传递常量
【发布时间】:2015-12-22 08:20:06
【问题描述】:

我正在编写一个小型皮质 M0+ 引导加载程序。我在下面有一个内联程序集,它通过从 Flash 中的应用程序位置加载堆栈指针和重置处理程序从引导加载程序启动主应用程序。

#define FLASH_APP_START 0x1000

[...]

    __asm(
            // Update stack pointer from user code vector table
            "LDR     r0, =%0 \n"
            "LDR     r1, [r0] \n"
            "MOV     sp, r1 \n"

            // Load user code reset handler and jump to the user code
            "LDR     r0, [r0, #4] \n"
            "BX      r0 \n"
            :
            : "X"(FLASH_APP_START)
            :
        );

编译这段代码时出现以下错误:

错误:错误的表达式 -- `ldr r0,=#4096'

GCC 在不应该存在的常量之前添加#。 如果我将第一行替换为以下内容,则效果很好。

LDR r0, =0x1000

所以问题是我如何使用定义的常量?

提前感谢您的帮助

【问题讨论】:

  • 一些想法:您正在更改此模板中的 r0 和 r1 而不会破坏它们。这似乎很糟糕。至于#,你可以试试%c0
  • gcc manual 中不正确地记录了作为文字池约束的大写“R”。大卫的建议是正确的;按照godbolt example 使用“%creg”修饰符。 The manual 在标题“修饰符描述”下有这个。
  • 内联汇编器和常量池上的related question

标签: c gcc arm inline-assembly


【解决方案1】:

首先这里没有理由使用内联汇编,简单的解决方案就是将此代码编写为普通的汇编语言文件。您可以在头文件中定义 FLASH_APP_START 宏,如果需要,您可以将其包含在程序集和 C 源文件中。

如果您仍想使用内联汇编,那么下一个最简单的解决方案是让编译器为您完成大部分工作,并将汇编语句减少到它不能做的事情:

    void ** const flash_vector_table = (void **) FLASH_APP_START;
    asm volatile ("mov sp, %[stack]\n\t"
                  "bx %[reset]\n"
                  :
                  :
                  [stack] "r" (flash_vector_table[0]),
                  [reset] "r" (flash_vector_table[1]));

【讨论】:

  • 应该如此。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多