ARM Cortex-M4,uint64_t和GCC 4.9上的va_arg

时间:2015-07-17 20:50:20

标签: memory-alignment cortex-m variadic-functions gcc4.9 unsigned-long-long-int

我有以下代码:

__attribute__((aligned(0x1000))) static void doVariadic(const uint32_t fmt, ...);

__attribute__((aligned(0x1000))) va_list ap;
__attribute__((aligned(0x1000))) uint32_t value1 = 0xABABABAB;
__attribute__((aligned(0x1000))) uint64_t value2 = 0xF0F0F0F0E1E1E1E1LLU;
__attribute__((aligned(0x1000))) uint32_t value3 = 0x24242424;
__attribute__((aligned(0x1000))) uint32_t arg1;
__attribute__((aligned(0x1000))) uint64_t arg2;
__attribute__((aligned(0x1000))) uint32_t arg3;


__attribute__((aligned(0x1000))) int main(void)
{
    doVariadic(0x0UL, value1, value2, value3);
}


__attribute__((aligned(0x1000))) static void doVariadic(const uint32_t fmt, ...)
{
    va_start(ap, fmt);

    arg1 = va_arg(ap, uint32_t);
    arg2 = va_arg(ap, uint64_t);
    arg3 = va_arg(ap, uint32_t);

    UNUSED(arg1);
    UNUSED(arg2);
    UNUSED(arg3);
}

执行此操作时,我会得到以下值:

arg1 = 0xABABABAB

arg2 = 0x24242424F0F0F0F0

arg3 = 0x010048E7

变量arg3似乎在Flash中包含一个地址。

我已经在某处读过这可能是由于堆栈对齐(这就是为什么你会看到所有这些对齐属性,特别是为什么我将我的变量外部化到函数范围之外)。 我还确保使用" -mabi = aapcs -std = c99"编译我的代码。标志。

当调用该函数时,我查看了{r0-r3}寄存器,它们似乎正确地正确包含了前3个参数(r2和r3包含小端字中的64位值)。

我注意到在异常期间(例如Hard Fault),可变参数功能正常。由于MCU在进入异常例程时设置为使用8位堆栈,因此可以解释发生的情况。

任何有助于理解真正发生的事情的人都会非常感激吗?怎么能修好?

1 个答案:

答案 0 :(得分:1)

在阅读以下主题后,我设法找到了自己的答案: http://comments.gmane.org/gmane.comp.hardware.microcontrollers.ethernut/14053

我误解了堆栈指针不需要对齐但显然完全是我的堆栈的顶部,这不是8字节对齐的。要实现这一点,我必须修改我的链接器文件:

_init_stack = (ORIGIN(ram) + LENGTH(ram) - 4);

要:

_init_stack = ((ORIGIN(ram) + LENGTH(ram) - 4) & 0xFFFFFFF8);