1

У меня есть следующий фрагмент кода:va_arg на ARM Cortex-M4, uint64_t и 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

арг2 = 0x24242424F0F0F0F0

arg3 = 0x010048E7

Переменная arg3 см ms, чтобы содержать адрес во Flash.

Я где-то читал, что это может быть связано с выравниванием стека (вот почему вы видите все эти атрибуты выравнивания и, особенно, почему я внедрил мои переменные за пределы области действия). Я также убедился, что мой код скомпилирован с использованием флагов «-mabi = aapcs -std = c99».

Я просмотрел регистры {r0-r3}, когда функция вызывается, и они, как представляется, правильно содержат первые 3 аргумента правильно (r2 и r3, содержащие 64-битное значение в словах с маленькой последовательностью).

Я заметил, что во время исключения (Hard Fault для примера) вариатор функционирует должным образом. И поскольку MCU настроен на использование 8-битного стека при вводе процедуры исключения, имеет смысл это объяснение того, что происходит.

Любая помощь в понимании того, что происходит на самом деле, будет действительно оценена? Как это можно исправить?

ответ

1

Я сумел найти свой собственный ответ после прочтения следующей темы: http://comments.gmane.org/gmane.comp.hardware.microcontrollers.ethernut/14053

я неправильно понял, что это не указатель стека, который должен быть выровнен, но, видимо, верхней частью моего стека целиком, который не был выровнен по 8 байт. Для достижения этой цели я должен был изменить свой файл линкера из:

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

To:

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