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