va_arg 在 ARM Cortex-M4、uint64_t 和 GCC 4.9 上
va_arg on ARM Cortex-M4, uint64_t and GCC 4.9
我有如下一段代码:
__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 位值)。
我注意到在异常期间(例如硬故障),可变参数功能正常。由于 MCU 设置为在进入异常例程时使用 8 位堆栈,因此这将是对正在发生的事情的解释。
如果能帮助您了解实际情况,我们将不胜感激?如何解决?
阅读以下主题后,我找到了自己的答案:
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);
我有如下一段代码:
__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 位值)。
我注意到在异常期间(例如硬故障),可变参数功能正常。由于 MCU 设置为在进入异常例程时使用 8 位堆栈,因此这将是对正在发生的事情的解释。
如果能帮助您了解实际情况,我们将不胜感激?如何解决?
阅读以下主题后,我找到了自己的答案: 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);