MSP430 манипулируем стеком

MSP430 манипулируем стеком

У новичка в прграммировании рано или поздно, возникает вопрос: "Что такое стек?".


Наиболее наглядным примером, для понимания, на мой взгляд, есть программа на языке ассемблера , которая просто добавляет данные в стек.

Стек - это структура данных присущая всем микропроцессорным устройствам. Чаще всего принцип работы стека сравнивают со стопкой тарелок: чтобы взять вторую сверху, нужно снять верхнюю. Часто стек называют магазином — по аналогии с магазином патронов в огнестрельном оружии (стрельба начнётся с патрона, заряженного последним).


Зачем нужен стек ?

Вы вряд ли будете писать программы, которые не будет использовать функции (подпрограммы). При вызове функции в стек копируется адрес для возврата после окончания выполнения данной подпрограммы. По окончании её выполнения адрес возвращается из стека в счетчик команд и программа продолжает выполняться с места после функции.
Также в стек необходимо помещать регистры, которые используются в данной подпрограмме (в языках высокого уровня этим занимается компилятор).
Все вышесказанное характерно для так называемого аппаратного стека. Надеюсь вы догадываетесь, что такая структура данных (LIFO - last in, first out) полезна далеко не только при работе на низком уровне. Часто возникает необходимость хранить данные в таком порядке (например известный алгоритм разбора арифметических выражений основан на работе со стеком), тогда программисты реализуют программный стек.

Как это работает?

Давайте разберем работу со стеком на примере контроллеров семейства MSP430.
В MSP430 стек основан на предекрементной схеме. Т.е. перед тем как вы записываете данные в стек он уменьшает адрес вершины стека (верхней тарелки). Бывает также постдекрементный/постинкрементный (вычитание/добавление вершины стека происходит после записи данных) и прединкрементный (перед записью адрес вершины увеличивается).
Если стек увеличивает свой адрес при записи данных, говорят о стеке растущем вверх, если же уменьшает - вниз. За хранения адреса вершины стека отвечает регистр SP.





Как видите адрес вершины по умолчанию у нас 0x0A00.

Рассмотрим вот такую программу:



PUSH #0123h       ; Помещение числа 0123h на вершину стека (TOS)
                           ; копируем данные из памяти
        MOV.W &0x0A00, R5
        MOV.W &0x09FE, R6
                           ; пишем еще два числа
        PUSH #9250h
        PUSH #0000h
                            ; выводим данные из стека
        POP  R8           
        POP  R9          
        POP  R10 



Что делает эта программа?

Командой PUSH мы помещаем данные 0123h в стек. Казалось бы этой командой мы запишем 0123h в память по адресу 0x0A00, но мы ведь помним, что стек у нас предекрементный. Поэтому сначала адрес уменьшается на 2 (0x0A00 - 2 = 0x09FE) и в ячейку с полученным адресом записываются данные.

Вот так выглядела память изначально:







После выполнения команды PUSH (красным выделены изменения):








Итак данные записались.
Проверим так ли это выполнив две команды пересылки (mov). Сначала получим данные из ячейки 0x0A00 и запишем их в регистр R5, а затем запишем в регистр R6 данные из ячейки 0x09FE.
После этого в регистрах будет данные:







Далее запишем еще два числа в стек, после чего будем из доставать при помощи команды POP. После выполнения ещё двух команд PUSH память в стеке будет выглядеть так:






При выполнении команд POP вершина стека будет увеличиваться на 2 при каждой команде, а в регистры R8-10 попадут данные: 0x0000, 0x9250 и 0x0123 соответственно.
При добавлении других данные память (которая все еще содержит данные, выведенные из стека) будет заполнена новыми значениями.

Проиллюстрировать работу со стеком можно так (слева на право):






Изначально адресом стека был 0x0A00, в нем хранились 0000. При выполнении PUSH верхушкой стека стала ячека ниже (с адресом 0x09FE) и в неё записались данные. С каждой следующей командой верхушка находиться ниже в памяти. При выполнении команды POP картина обратная.





; MSP430 Assembler Code Template для применения с  TI Code Composer Studio
; Эта программа демонстрирует использование стека.
; Rob Frohne November, 2015
; Эта программа предназначена для того, чтобы поэкспериментировать со стеком!
;-------------------------------------------------------------------------------
            .cdecls C,LIST,"msp430.h"       ; Подключаем заголовочный файл вашего микроконтроллера
            
;-------------------------------------------------------------------------------
            .def    RESET                   ; Экспорт точки входа программы, чтобы сделать ее известной  линкеру.
;-------------------------------------------------------------------------------
            .text                             ; Ассемблирование в память программ.
            .retain                          ; Переопределение ELF, условная компоновку и сохранение текущего раздела.
            .retainrefs                     ; И сохранение любых разделов, которые имеют ссылки на текущий раздел.                                           

;-------------------------------------------------------------------------------
RESET       mov.w   #__STACK_END,SP         ; Инициализация указателя стека
StopWDT     mov.w   #WDTPW|WDTHOLD,&WDTCTL  ; Остановка  watchdog timer
;-------------------------------------------------------------------------------
; Основной цикл здесь
;-------------------------------------------------------------------------------
            mov.w    #0xffff,r6
            mov.w    #0x000f,r7
loop1    push    r6
            dec        r7
            jnz        loop1

            mov.w    #0x000f,r7
loop2        pop        r6
            dec        r7
            jnz        loop2

            mov.w    #0x0004,r4
            mov.w    #0x0005,r5
            mov.b    #0xff06,r6
            call    #subroutine1
            mov.w    r4,&0x43f2
            jmp    $

subroutine1    push.w    r4
            push.w    r5
            push.b    r6
            mov.w    #0x4444,r4
            mov.w    #0x5555,r5
            mov.w    #0x6666,r6
            pop.b    r6
            pop.w    r5
            pop.w    r4
            ret

                                            

;-------------------------------------------------------------------------------
; Определение указателя стека
;-------------------------------------------------------------------------------
            .global __STACK_END
            .sect   .stack
            
;-------------------------------------------------------------------------------
; Векторы прерываний
;-------------------------------------------------------------------------------
            .sect   ".reset"                ; MSP430 RESET Vector    вектор сброса
            .short  RESET                   
Написать:
18:40
3496
Нет комментариев. Ваш будет первым!