Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: AVR STACK
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > GNU/OpenSource средства разработки
demiurg_spb
Написал макросы для работы со стеком...
Но я не являюсь спецом по ASM в AVRGCC.
Прошу великих Гуру окинуть сие творчество на передмет косяков...
И вообще, можно-ли в GCC использовать стек в таком ключе или есть нюансы?
Код
// ============================================================================
#define __avr_stack_pop()                 \
(__extension__({                          \
    uint8_t __result;                     \
    __asm__ __volatile__                  \
    (                                     \
        "pop %0"            "\n\t"        \
        : "=r" (__result)                 \
        :                                 \
    );                                    \
    __result;                             \
}))

// ============================================================================
#define __avr_stack_push(value)           \
(__extension__({                          \
    uint8_t __value = (uint8_t)value;     \
    __asm__ __volatile__                  \
    (                                     \
        "push %0"            "\n\t"       \
        :                                 \
        : "r" (__value)                   \
    );                                    \
}))

Тест:
Код
#define stack_push  __avr_stack_push
#define stack_pop   __avr_stack_pop
    unsigned char i = 0;
    do
    {
        stack_push(i);
        i = stack_pop();
    } while (++i<5);

Выход:
Код
    cabe:    80 e0           ldi    r24, 0x00; 0
    cac0:    8f 93           push    r24
    cac2:    8f 91           pop    r24
    cac4:    8f 5f           subi    r24, 0xFF; 255
    cac6:    85 30           cpi    r24, 0x05; 5
    cac8:    d8 f3           brcs    .-10     ; 0xcac0 <main+0x2>
KRS
а для чего вам это надо?
demiurg_spb
Парсить удобно...

Да ещё была одна задумка, но она похоже накрылсь...

Хотел сохранять номер пункта родительского меню для последующего восстановления при возврате -
но пока не работает - MCU ресетится...
Разбираюсь в чём дело.
Если push и pop в одной процедуре - всё ок....
Сергей Борщ
Цитата(demiurg_spb @ Aug 6 2008, 15:02) *
Если push и pop в одной процедуре - всё ок....
Естественно. Потому что в другой процедуре на стек еще положен адрес возврата, локальные переменные, сохраненный SREG. Даже в одной процедуре в теле компилятор может положить на стек временную переменную и вся ваша стройная система рухнет. По макросу: поскольку push изменяет ОЗУ, совсем честно было бы указать memory в списке clobber
demiurg_spb
Цитата(Сергей Борщ @ Aug 6 2008, 17:11) *
Естественно. Потому что в другой процедуре на стек еще положен адрес возврата, локальные переменные, сохраненный SREG. Даже в одной процедуре в теле компилятор может положить на стек временную переменную и вся ваша стройная система рухнет.

С адресом возврата я согласен.
Из Вашей ремарки можно сделать не совсем правильный вывод о том, что компилятор использует лишь стек, а как же куча?
Когда она используется?
К слову, бывает, что компиляторы разделяют аппаратный стек и программный ибо он быстрее на некоторых системах...
Я думаю что и для AVR архитектуры это тоже м.б. разумно...

Цитата(Сергей Борщ @ Aug 6 2008, 17:11) *
По макросу: поскольку push изменяет ОЗУ, совсем честно было бы указать memory в списке clobber

Доработал. Спасибо за совет!
Код
// ============================================================================
#define __avr_stack_pop()                 \
(__extension__({                          \
    uint8_t __result;                     \
    __asm__ __volatile__                  \
    (                                     \
        "pop %0"            "\n\t"        \
        : "=r" (__result)                 \
        :                                 \
        : "memory"                        \
    );                                    \
    __result;                             \
}))

// ============================================================================
#define __avr_stack_push(value)           \
(__extension__({                          \
    uint8_t __value = (uint8_t)value;     \
    __asm__ __volatile__                  \
    (                                     \
        "push %0"            "\n\t"       \
        :                                 \
        : "r" (__value)                   \
        : "memory"                        \
    );                                    \
}))

Ещё раз убеждаюсь, что задавать правильные вопросы очень полезно для здоровьяsmile.gif
Сергей Борщ
Цитата(demiurg_spb @ Aug 6 2008, 18:39) *
С адресом возврата я согласен.
Из Вашей ремарки можно сделать не совсем правильный вывод о том, что компилятор использует лишь стек, а как же куча? Когда она используется?
Компилятор "сам" использует кучу только в одном случае - в С++ при создании объектов через new. В С кучу использует программист, через вызов функций malloc/free.
Цитата(demiurg_spb @ Aug 6 2008, 18:39) *
К слову, бывает, что компиляторы разделяют аппаратный стек и программный ибо он быстрее на некоторых системах...
Я думаю что и для AVR архитектуры это тоже м.б. разумно...
Да, есть у такого подхода плюсы, есть минусы. В данном случае вы спрашивали по avr-gcc, а у него всего один стек.
demiurg_spb
Спасибо за разъяснение. Буду копать под кучуsmile.gif
zltigo
Цитата(Сергей Борщ @ Aug 6 2008, 18:32) *
Компилятор "сам" использует кучу только в одном случае - в С++....
В С кучу использует программист, через вызов функций malloc/free.

Не совсем так - компилятор-то "сам" не использует, но некоторые вполне сишные библиотечные функции heap вынуждены пользовать - на вскидку strdup(), time()...
Сергей Борщ
Цитата(zltigo @ Aug 6 2008, 21:01) *
Не совсем так - компилятор-то "сам" не использует, но некоторые вполне сишные библиотечные функции heap вынуждены пользовать - на вскидку strdup(), time()...
Естественно, но это функции, в исходнике которых явно указаны malloc/free. При использовании new компилятор вставляет malloc/free "от себя". Хотя... new тоже пишет программист.
ReAl
Цитата(demiurg_spb @ Aug 6 2008, 15:02) *
Да ещё была одна задумка, но она похоже накрылсь...
Хотел сохранять номер пункта родительского меню для последующего восстановления при возврате -
но пока не работает - MCU ресетится...
А зачем для этого использовать аппаратный стек контроллера?
Сделать свой отдельно.
Пусть максимум вложенности меню будет MAX_SUBMENU - тогда по сусекам всё равно придётся выделить столько байт на восстановления. Соберём их в одном месте
Код
static uint8_t menu_stack[MAX_SUBMENU];
static uint8_t menu_stack_ptr = 0;

void push_index( uint8_t index)
{
    if( menu_stack_ptr < MAX_SUBMENU )
        menu_stack[ menu_stack_ptr++ ] = index;
}

uint8_t pop_index()
{
    return menu_stack_ptr ? menu_stack[--menu_stack_ptr] : 0;        
}
demiurg_spb
Именно так я и сделал.
Прежде хотелось выпендриться - не вышлоsmile.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.