Обзор работы со стеком » History » Version 21
krufter_multiclet, 04/04/2013 11:44 AM
| 1 | 1 | krufter_multiclet | h1. Обзор работы со стеком |
|---|---|---|---|
| 2 | 1 | krufter_multiclet | |
| 3 | 21 | krufter_multiclet | *Стек вызовов* (от англ. call stack; применительно к процессорам — просто «стек») — в теории вычислительных систем, LIFO-стек, хранящий информацию для возврата управления из подпрограмм (процедур) в программу (или подпрограмму, при вложенных или рекурсивных вызовах) и/или для возврата в программу из обработчика прерывания (в том числе при переключении задач в многозадачной среде). |
| 4 | 21 | krufter_multiclet | |
| 5 | 21 | krufter_multiclet | При вызове подпрограммы или возникновении прерывания, в стек заносится адрес возврата — адрес в памяти следующей инструкции (в нашем случае параграф) приостановленной программы и управление передается подпрограмме или подпрограмме-обработчику. При последующем вложенном или рекурсивном вызове, прерывании подпрограммы или обработчика прерывания, в стек заносится очередной адрес возврата и т. д. |
| 6 | 21 | krufter_multiclet | |
| 7 | 21 | krufter_multiclet | При возврате из подпрограммы или обработчика прерывания, адрес возврата снимается со стека и управление передается на следующую инструкцию (в нашем случае параграф) приостановленной (под-)программы. |
| 8 | 1 | krufter_multiclet | |
| 9 | 1 | krufter_multiclet | Стек в мультиклеточном процессоре организован при помощи индексных регистров 38,39. |
| 10 | 17 | krufter_multiclet | Регистр 38 имеет имя BP (база стека), регистр 39 называется SP (вершина стека). |
| 11 | 1 | krufter_multiclet | |
| 12 | 1 | krufter_multiclet | Стек растёт от конца памяти данных и структурируется по кадрам. Один кадр состоит из группы элементов, находящихся |
| 13 | 2 | krufter_multiclet | между SP и BP (между вершиной и базой стека). Один элемент кадра является 32-х битной ячейкой памяти. |
| 14 | 5 | krufter_multiclet | Рассмотрим структуру стека при вызове на Си ассемблерной функции типа void, которая не возвращает результат и |
| 15 | 6 | krufter_multiclet | имеет два аргумента, например *void MDIO_WR(int phy_addr, int reg_num)*: |
| 16 | 3 | krufter_multiclet | |
| 17 | 4 | krufter_multiclet | !Stack_void.jpg! |
| 18 | 5 | krufter_multiclet | |
| 19 | 1 | krufter_multiclet | Рис 1. Структура стека функции void |
| 20 | 6 | krufter_multiclet | |
| 21 | 6 | krufter_multiclet | +Адрес возврата+ - адрес для возвращения обратно в Си программу |
| 22 | 6 | krufter_multiclet | +Аргумент1+ - значение переменной phy_addr |
| 23 | 6 | krufter_multiclet | +Аргумент2+ - значение переменной reg_num |
| 24 | 6 | krufter_multiclet | +Адрес BP+ - значение адреса, по которому располагалась база предыдущего кадра |
| 25 | 7 | krufter_multiclet | |
| 26 | 7 | krufter_multiclet | Вершина стека (SP) находится на 3 позиции выше базы стека (BP). |
| 27 | 7 | krufter_multiclet | |
| 28 | 10 | krufter_multiclet | Для функции типа int, которая возвращает результат структура кадра немного изменится(появится поле для возвращаемого значения). |
| 29 | 8 | krufter_multiclet | Например, рассмотрим следующую функцию *int MDIO_RD(int phy_addr, int reg_num)*: |
| 30 | 8 | krufter_multiclet | |
| 31 | 8 | krufter_multiclet | !Stack_int.jpg! |
| 32 | 8 | krufter_multiclet | |
| 33 | 12 | krufter_multiclet | Рис 2. Структура стека функции int |
| 34 | 9 | krufter_multiclet | |
| 35 | 9 | krufter_multiclet | +Адрес возврата+ - адрес для возвращения обратно в Си программу |
| 36 | 9 | krufter_multiclet | +Результат+ - значение возвращаемое функцией в Си |
| 37 | 9 | krufter_multiclet | +Аргумент1+ - значение переменной phy_addr |
| 38 | 9 | krufter_multiclet | +Аргумент2+ - значение переменной reg_num |
| 39 | 9 | krufter_multiclet | +Адрес BP+ - значение адреса, по которому располагалась база предыдущего кадра |
| 40 | 9 | krufter_multiclet | |
| 41 | 1 | krufter_multiclet | Вершина стека (SP) находится на 4 позиции выше базы стека (BP). |
| 42 | 12 | krufter_multiclet | |
| 43 | 12 | krufter_multiclet | Стек разумеется можно использовать для своих нужд, но при этом следует учесть, что в ассемблерном файле в котором реализована функция Си |
| 44 | 12 | krufter_multiclet | должно быть сохранение исходных значений вершины и базы стека, а в конце ассемблерного файла их восстановление. |
| 45 | 14 | krufter_multiclet | Рассмотрим пример сохранения исходных значений SP,BP и выделение кадра в размерностью *56/4* (SP-BP), в котором можно разместить 14 своих |
| 46 | 12 | krufter_multiclet | ячеек по 4 байта: |
| 47 | 12 | krufter_multiclet | <pre> |
| 48 | 12 | krufter_multiclet | prologe: |
| 49 | 12 | krufter_multiclet | getl #SP |
| 50 | 12 | krufter_multiclet | getl #BP |
| 51 | 12 | krufter_multiclet | subl @2, 60 |
| 52 | 12 | krufter_multiclet | wrl @2, #SP, -4 |
| 53 | 12 | krufter_multiclet | setl #SP, @2 |
| 54 | 12 | krufter_multiclet | subl @5, 4 |
| 55 | 12 | krufter_multiclet | setl #BP, @1 |
| 56 | 12 | krufter_multiclet | jmp get_put |
| 57 | 12 | krufter_multiclet | complete |
| 58 | 12 | krufter_multiclet | </pre> |
| 59 | 12 | krufter_multiclet | |
| 60 | 12 | krufter_multiclet | Для восстановления вершины и базы стека можно использовать следующий универсальный параграф: |
| 61 | 12 | krufter_multiclet | |
| 62 | 12 | krufter_multiclet | <pre> |
| 63 | 12 | krufter_multiclet | epiloge: |
| 64 | 12 | krufter_multiclet | getl #BP |
| 65 | 12 | krufter_multiclet | addl @1, 4 |
| 66 | 12 | krufter_multiclet | setl #SP, @1 |
| 67 | 12 | krufter_multiclet | rdl #BP |
| 68 | 12 | krufter_multiclet | setl #BP, @1 |
| 69 | 12 | krufter_multiclet | rdl RDATA |
| 70 | 12 | krufter_multiclet | addl @6, 8 |
| 71 | 12 | krufter_multiclet | wrl @2, @1 |
| 72 | 12 | krufter_multiclet | jmp end_ret |
| 73 | 12 | krufter_multiclet | complete |
| 74 | 12 | krufter_multiclet | </pre> |
| 75 | 12 | krufter_multiclet | |
| 76 | 20 | krufter_multiclet | Команды getl, setl записывают значение в индексный регистр, а команды wrl, rdl - в память данных по адресу, который записан в индексном регистре или получен в результате сложения. |
| 77 | 13 | krufter_multiclet | |
| 78 | 13 | krufter_multiclet | !Stack_add.jpg! |
| 79 | 13 | krufter_multiclet | |
| 80 | 14 | krufter_multiclet | Рис 3.Выделение кадра в размерностью *56/4* |
| 81 | 15 | krufter_multiclet | |
| 82 | 15 | krufter_multiclet | Ознакомиться с примером работы со стеком можно в хранилище в папке LDM_MCP04->Test_time_delay |