реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Перемещение функции в памяти ..., Нужен совет
3.14
сообщение Mar 24 2005, 09:35
Сообщение #1


Их либе дих ...
******

Группа: СуперМодераторы
Сообщений: 2 010
Регистрация: 6-09-04
Из: Russia, Izhevsk
Пользователь №: 609



Как в C коректнее скопировать функцию из одной области памяти в другую и затем вызвать из нового местоположения.


--------------------
Усы, борода и кеды - вот мои документы :)
Go to the top of the page
 
+Quote Post
alex_k
сообщение Mar 24 2005, 10:01
Сообщение #2


Частый гость
**

Группа: Свой
Сообщений: 119
Регистрация: 4-03-05
Пользователь №: 3 067



Размышления вслух... Если после компиляции си-компилятором (не известно ж
какой компилятор и что за процессор), мы получаем код, адресация переходов в котором выполнена в относительной системе, относительно текущеего адреса, тогда такую функцию в принципе можно копировать из
одного места памяти в другое. Дальше, получить адрес функции в си не проблема - просто указатель на функцию. Остается проблема, как узнать длинну кода занимаемого функцией. Если длинна изместна, то поидее можно копировать в выделенный буфер, например memcpy, ну а далее вызывать по новому указателю...
Go to the top of the page
 
+Quote Post
makc
сообщение Mar 24 2005, 10:05
Сообщение #3


Гуру
******

Группа: Админы
Сообщений: 3 621
Регистрация: 18-10-04
Из: Москва
Пользователь №: 904



Цитата(3.14 @ Mar 24 2005, 12:35)
Как в C коректнее скопировать функцию из одной области памяти в другую и затем вызвать из нового местоположения.
*


Абсолютно корректно это сделать не получится, т.к. этот вопрос не предусмотрен стандартом, но можно сделать следующее:

Объявить две функции - копируемую и еще одну, вспомогательную:
Код
static void source_f()
{
....
}

static void source_f_end()
{
}


После этого в программе можно объявить буфер и скопировать туда нужную функцию и вызвать ее:
Код
typedef  void   (*call_pointer)(void)
char  buffer[ desired ];
call_pointer   pointer;
memcpy( buffer, source_f, (size_t)(source_f_end - source_f) );
pointer = (call_pointer)buffer;
pointer();


но подобный метод накладывает сильные ограничения на то, что может быть написано в копируемой функции. Так, например, если в ней есть вызовы других функций, то необходимо изменить их непосредственные вызовы на вызовы по указателям, переданным вызываемой функции. И т.д.


--------------------
BR, Makc
В недуге рождены, вскормлены тленом, подлежим распаду. (с) У.Фолкнер.
Go to the top of the page
 
+Quote Post
olefil
сообщение Mar 24 2005, 11:18
Сообщение #4


Частый гость
**

Группа: Свой
Сообщений: 146
Регистрация: 8-12-04
Пользователь №: 1 407



От части этот механизм представлен в оверлеях, когда несколько функций могут занимать одно и то же место в памяти, это решает вопрос маленькой памяти, а копирование кода, точно не к чму не приведет, правда некоторые функции можно переносить таким образом, но только те которые представленны в понятном asm эквиваленте, т.е если там нет каких либо видов оптимизаии и вызовов функции по косвенному смещению от точки вызова. Тут конечно можно примеров много написать чего можно, а чего нельзя, но лучше таких вариантов с кодом не проделывать, а иначе программа может начать вести себя совершенно не вероятным образом.
Go to the top of the page
 
+Quote Post
3.14
сообщение Mar 24 2005, 11:20
Сообщение #5


Их либе дих ...
******

Группа: СуперМодераторы
Сообщений: 2 010
Регистрация: 6-09-04
Из: Russia, Izhevsk
Пользователь №: 609



2 max
Я правильно понял Ваш пример?
Копируемая функция source_f() переносится по адресу функции source_f_end(), вызов пересенной функции осуществляется через pointer() ?

Попробовал пример сунуть в VDSP4.0.
В дебуггере после memcpy() функция source_f_end() не меняет своего содержимого. В железе все то же виснет sad.gif


--------------------
Усы, борода и кеды - вот мои документы :)
Go to the top of the page
 
+Quote Post
olefil
сообщение Mar 24 2005, 11:24
Сообщение #6


Частый гость
**

Группа: Свой
Сообщений: 146
Регистрация: 8-12-04
Пользователь №: 1 407



Компилятор в VDSP может не понимать того, что вы делаете и я больше чем увероен, что это так!!!
Go to the top of the page
 
+Quote Post
3.14
сообщение Mar 24 2005, 11:25
Сообщение #7


Их либе дих ...
******

Группа: СуперМодераторы
Сообщений: 2 010
Регистрация: 6-09-04
Из: Russia, Izhevsk
Пользователь №: 609



2 olefil
Я по большому счету, пытаюсь перенести asm примеры с оверлеями на C. Пока не получается sad.gif


--------------------
Усы, борода и кеды - вот мои документы :)
Go to the top of the page
 
+Quote Post
olefil
сообщение Mar 24 2005, 11:27
Сообщение #8


Частый гость
**

Группа: Свой
Сообщений: 146
Регистрация: 8-12-04
Пользователь №: 1 407



А вчем конкретная проблема? Может чем помогу?
Go to the top of the page
 
+Quote Post
bve
сообщение Mar 24 2005, 11:51
Сообщение #9


Местный
***

Группа: Свой
Сообщений: 316
Регистрация: 20-02-05
Из: Ленинградская обл.
Пользователь №: 2 765



Есть еще одна проблема, зависящая от компилятора и оптимизации -
передача параметров в подпрограмму. Т.е. необходимо копировать не только
тело самой функции, но и кусок кода ее вызывающий, либо запихивать параметры самому в необходимые регистры/ячейки. Не надо также забывать об изменении указателя фрейма, если таковой имеется.
Go to the top of the page
 
+Quote Post
makc
сообщение Mar 24 2005, 11:53
Сообщение #10


Гуру
******

Группа: Админы
Сообщений: 3 621
Регистрация: 18-10-04
Из: Москва
Пользователь №: 904



Цитата(3.14 @ Mar 24 2005, 14:20)
2 max
Я правильно понял Ваш пример?
Копируемая функция source_f() переносится по адресу функции source_f_end(), вызов пересенной функции осуществляется через pointer() ?

Попробовал пример сунуть в VDSP4.0.
В дебуггере после memcpy() функция source_f_end() не меняет своего содержимого. В железе все то же виснет sad.gif
*


Не совсем так. При решении этой задачи есть две проблемы:
1. Определение размеров копируемой функции.
2. Вызов функции из того места, куда она была скопирована.

1. Для решения этой проблемы вводится функция source_f_end(), которая будет лежать после копируемой функции, т.е. адрес source_f_end - это адрес следующего байта после тела копируемой функции. Таким образом, разность source_f_end - source_f нам даст размер копируемой функции.
2. Функцию копируем в объявленный буфер. Поэтому функция source_f_end и не должна изменить своего содержимого - это только маркер. Буфер для копирования лучше объявить не локальным, а глобальным, тогда будет меньше проблем, т.к. не все процессоры умеют исполнять код из стека. Вызов осуществляется через pointer, значение которого должно быть равно адресу начала буфера, куда была скопирована функция.

А что есть в самой копируемой функции? Ведь если там есть прямые вызовы других функций и обращение к глобальным переменным, то она работать не будет. Т.к. как правило их смещения вычисляются линкером при линковке и едут непредсказуемым образом при копировании функции. Может быть в этом проблема?


--------------------
BR, Makc
В недуге рождены, вскормлены тленом, подлежим распаду. (с) У.Фолкнер.
Go to the top of the page
 
+Quote Post
makc
сообщение Mar 24 2005, 11:57
Сообщение #11


Гуру
******

Группа: Админы
Сообщений: 3 621
Регистрация: 18-10-04
Из: Москва
Пользователь №: 904



Цитата(bve @ Mar 24 2005, 14:51)
Есть еще одна проблема, зависящая от компилятора и оптимизации -
передача параметров в подпрограмму. Т.е. необходимо копировать не только
тело самой функции, но и кусок кода ее  вызывающий, либо запихивать параметры самому в необходимые регистры/ячейки. Не надо также забывать об изменении указателя фрейма, если таковой имеется.
*


Минуточку... Есть стандартный способ передачи параметров в подпрограмму, который используется повсеместно (в проекте) одним компилятором. Поэтому нужно иметь правильный прототип функции и тогда вызов будет происходить корректно.

Что касается фрейма (я так понимаю, что речь идет о фрейме стека), то он вычисляется исходя из текущего значения указателя стека. А в некоторых случаях он вообще не используется (например у gcc при -fomit-frame-pointer).

Так что, как мне кажется, проблемы передачи параметров нет.


--------------------
BR, Makc
В недуге рождены, вскормлены тленом, подлежим распаду. (с) У.Фолкнер.
Go to the top of the page
 
+Quote Post
olefil
сообщение Mar 24 2005, 12:03
Сообщение #12


Частый гость
**

Группа: Свой
Сообщений: 146
Регистрация: 8-12-04
Пользователь №: 1 407



Скорее это так, проблем с передачей параметров действительно нет, но вот от компиляции конкретным оброзом внутренности программы Sharc очень сильно изменяются. И если использовать оптимизацию, то что эта функция делает, знает только компилятор.
Go to the top of the page
 
+Quote Post
3.14
сообщение Mar 24 2005, 13:06
Сообщение #13


Их либе дих ...
******

Группа: СуперМодераторы
Сообщений: 2 010
Регистрация: 6-09-04
Из: Russia, Izhevsk
Пользователь №: 609



2 maks
<1. Для решения этой проблемы вводится функция source_f_end(), которая будет лежать после копируемой функции...>
В VDSP такая фишка не проходит, он в памяти располагает не по объявлению а по вызову.
Еще имеется специфика ADSP, регистры имеют разрядность 40 бит, ширина инструкций 48 бит. В моем случае копируемая функция находится в SDRAM, разрядность данных 32 разряда, надо упаковывать в 48 бит.

<Есть стандартный способ передачи параметров в подпрограмму>
А в чем он заключается?
Я решил сделать так, фунции которые будут копироваться в место исполнения общатся с внешней (програмной) средой будут посредством глобального массива аргументов, элементы которого для определенных функций будут являться входными и выходными параметрами.

2 olefil
В общем, взял пример fft_ovly2
Вот кусок менеджера оверлеев отвечающий за DMA передачу
Код
 i8 = runAddresses;
 i0 = liveAddresses;
 r0=0;      
//   Disable DMA
 dm(DMAC0) = r0;  
//   Set DMA external pointer to overlay live address
 r0=dm(m0,i0);
 dm(EIEP0)=r0;\
// Set DMA internal pointer to overlay run address  
 r0=pm(m8,i8);
 dm(IIEP0)=r0;\
 i0=runWordSize;  //  Number of words stored in internal memory  
//                   Most likely the word size will be 48 bits  
//                   for instructions.        
//   Set DMA external modifier
 r0=1;
 dm(EMEP0)=r0;
 i8=liveWordSize; //  Number of words stored in external memory
//                   Most likely the word size will be 32 or16  
//                   bits for external storage.    
//   Set DMA internal modify to 1
 dm(IMEP0)=r0;
//   Set DMA internal count to Overlay run size.    
 r0=dm(m0,i0);
 dm(CEP0)=r0;
//   Set DMA external count to Overlay live size.    
 r0=pm(m8,i8);
 dm(ECEP0)=r0;
//   DMA enabled, instruction word, Master, 48-32 packing    
 r0=0x2e1;
 dm(DMAC0)=r0;


Переписал это на C

Код
 *pDMAC0=0;
 *pEIEP0=pointerDest;
 *pIIEP0=pointerTarget;
 *pEMEP0=1;
 *pIMEP0=1;
 *pCEP0=0x20;
 *pECEP0=0x20;
 *pDMAC0=0x2e1;

Размер функции в которую копируется 1kword.
Копируемая функция размером 10word.

Разместил копируемую функцию во внутренней памяти, содержимое первых шести слов :
Код
043ff8000000 0f0200000008 ad02fffffffe
10010000c009 013e00001012 11000000c009


Далее разместил копируемую функцию в SDRAM, после завершения работы DMA, содержимое скопированной функции:
Код
00000000F800 00000008043F 0F020000FFFE
AD02FFFF0000 0000C0090000 000010121001


???


--------------------
Усы, борода и кеды - вот мои документы :)
Go to the top of the page
 
+Quote Post
sweetin
сообщение Mar 24 2005, 13:20
Сообщение #14





Группа: Новичок
Сообщений: 8
Регистрация: 3-01-05
Пользователь №: 1 791



Цитата(3.14 @ Mar 24 2005, 16:06)
<Есть стандартный способ передачи параметров в подпрограмму>
А в чем он заключается?


через general-purpose регистры. а если параметров много - через стековый фрейм функции из которой производится вызов.
Go to the top of the page
 
+Quote Post
olefil
сообщение Mar 24 2005, 13:47
Сообщение #15


Частый гость
**

Группа: Свой
Сообщений: 146
Регистрация: 8-12-04
Пользователь №: 1 407



У меня ща все платы в доработке не фига не попробовать. Но вроде код на первый взгляд правельный. Правда на счет упаковки 48-32 трудно сказать, я сейчас немного другой работой занимаюсь, но вроде похоже на правду. А че показывает VDSP, если в debugger код посмотреть. Блин у меня где-то был исходник для overley'ев копировал функции из внутренней памяти во внешнюю правда не по DMA, а через PX регистр все работало.
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th June 2025 - 22:17
Рейтинг@Mail.ru


Страница сгенерированна за 0.01507 секунд с 7
ELECTRONIX ©2004-2016