Обзор работы со стеком » History » Version 20
Version 19 (krufter_multiclet, 04/03/2013 11:54 AM) → Version 20/21 (krufter_multiclet, 04/03/2013 11:54 AM)
h1. Обзор работы со стеком
Стек необходим прежде всего для взаимодействия Си компилятора и ассемблера: передача аргументов функций,
передача параметров, сохранение значений для возврата в функцию, возврат в Си результатов и т.п.
Стек в мультиклеточном процессоре организован при помощи индексных регистров 38,39.
Регистр 38 имеет имя BP (база стека), регистр 39 называется SP (вершина стека).
Стек растёт от конца памяти данных и структурируется по кадрам. Один кадр состоит из группы элементов, находящихся
между SP и BP (между вершиной и базой стека). Один элемент кадра является 32-х битной ячейкой памяти.
Рассмотрим структуру стека при вызове на Си ассемблерной функции типа void, которая не возвращает результат и
имеет два аргумента, например *void MDIO_WR(int phy_addr, int reg_num)*:
!Stack_void.jpg!
Рис 1. Структура стека функции void
+Адрес возврата+ - адрес для возвращения обратно в Си программу
+Аргумент1+ - значение переменной phy_addr
+Аргумент2+ - значение переменной reg_num
+Адрес BP+ - значение адреса, по которому располагалась база предыдущего кадра
Вершина стека (SP) находится на 3 позиции выше базы стека (BP).
Для функции типа int, которая возвращает результат структура кадра немного изменится(появится поле для возвращаемого значения).
Например, рассмотрим следующую функцию *int MDIO_RD(int phy_addr, int reg_num)*:
!Stack_int.jpg!
Рис 2. Структура стека функции int
+Адрес возврата+ - адрес для возвращения обратно в Си программу
+Результат+ - значение возвращаемое функцией в Си
+Аргумент1+ - значение переменной phy_addr
+Аргумент2+ - значение переменной reg_num
+Адрес BP+ - значение адреса, по которому располагалась база предыдущего кадра
Вершина стека (SP) находится на 4 позиции выше базы стека (BP).
Стек разумеется можно использовать для своих нужд, но при этом следует учесть, что в ассемблерном файле в котором реализована функция Си
должно быть сохранение исходных значений вершины и базы стека, а в конце ассемблерного файла их восстановление.
Рассмотрим пример сохранения исходных значений SP,BP и выделение кадра в размерностью *56/4* (SP-BP), в котором можно разместить 14 своих
ячеек по 4 байта:
<pre>
prologe:
getl #SP
getl #BP
subl @2, 60
wrl @2, #SP, -4
setl #SP, @2
subl @5, 4
setl #BP, @1
jmp get_put
complete
</pre>
Для восстановления вершины и базы стека можно использовать следующий универсальный параграф:
<pre>
epiloge:
getl #BP
addl @1, 4
setl #SP, @1
rdl #BP
setl #BP, @1
rdl RDATA
addl @6, 8
wrl @2, @1
jmp end_ret
complete
</pre>
Команды getl, setl записывают значение в индексный регистр, а команды wrl, rdl - в память данных по адресу, адресу который записан в индексном регистре или получен в результате сложения.
!Stack_add.jpg!
Рис 3.Выделение кадра в размерностью *56/4*
Ознакомиться с примером работы со стеком можно в хранилище в папке LDM_MCP04->Test_time_delay
Стек необходим прежде всего для взаимодействия Си компилятора и ассемблера: передача аргументов функций,
передача параметров, сохранение значений для возврата в функцию, возврат в Си результатов и т.п.
Стек в мультиклеточном процессоре организован при помощи индексных регистров 38,39.
Регистр 38 имеет имя BP (база стека), регистр 39 называется SP (вершина стека).
Стек растёт от конца памяти данных и структурируется по кадрам. Один кадр состоит из группы элементов, находящихся
между SP и BP (между вершиной и базой стека). Один элемент кадра является 32-х битной ячейкой памяти.
Рассмотрим структуру стека при вызове на Си ассемблерной функции типа void, которая не возвращает результат и
имеет два аргумента, например *void MDIO_WR(int phy_addr, int reg_num)*:
!Stack_void.jpg!
Рис 1. Структура стека функции void
+Адрес возврата+ - адрес для возвращения обратно в Си программу
+Аргумент1+ - значение переменной phy_addr
+Аргумент2+ - значение переменной reg_num
+Адрес BP+ - значение адреса, по которому располагалась база предыдущего кадра
Вершина стека (SP) находится на 3 позиции выше базы стека (BP).
Для функции типа int, которая возвращает результат структура кадра немного изменится(появится поле для возвращаемого значения).
Например, рассмотрим следующую функцию *int MDIO_RD(int phy_addr, int reg_num)*:
!Stack_int.jpg!
Рис 2. Структура стека функции int
+Адрес возврата+ - адрес для возвращения обратно в Си программу
+Результат+ - значение возвращаемое функцией в Си
+Аргумент1+ - значение переменной phy_addr
+Аргумент2+ - значение переменной reg_num
+Адрес BP+ - значение адреса, по которому располагалась база предыдущего кадра
Вершина стека (SP) находится на 4 позиции выше базы стека (BP).
Стек разумеется можно использовать для своих нужд, но при этом следует учесть, что в ассемблерном файле в котором реализована функция Си
должно быть сохранение исходных значений вершины и базы стека, а в конце ассемблерного файла их восстановление.
Рассмотрим пример сохранения исходных значений SP,BP и выделение кадра в размерностью *56/4* (SP-BP), в котором можно разместить 14 своих
ячеек по 4 байта:
<pre>
prologe:
getl #SP
getl #BP
subl @2, 60
wrl @2, #SP, -4
setl #SP, @2
subl @5, 4
setl #BP, @1
jmp get_put
complete
</pre>
Для восстановления вершины и базы стека можно использовать следующий универсальный параграф:
<pre>
epiloge:
getl #BP
addl @1, 4
setl #SP, @1
rdl #BP
setl #BP, @1
rdl RDATA
addl @6, 8
wrl @2, @1
jmp end_ret
complete
</pre>
Команды getl, setl записывают значение в индексный регистр, а команды wrl, rdl - в память данных по адресу, адресу который записан в индексном регистре или получен в результате сложения.
!Stack_add.jpg!
Рис 3.Выделение кадра в размерностью *56/4*
Ознакомиться с примером работы со стеком можно в хранилище в папке LDM_MCP04->Test_time_delay