3.14 0 24 марта, 2005 Опубликовано 24 марта, 2005 · Жалоба Как в C коректнее скопировать функцию из одной области памяти в другую и затем вызвать из нового местоположения. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alex_k 0 24 марта, 2005 Опубликовано 24 марта, 2005 · Жалоба Размышления вслух... Если после компиляции си-компилятором (не известно ж какой компилятор и что за процессор), мы получаем код, адресация переходов в котором выполнена в относительной системе, относительно текущеего адреса, тогда такую функцию в принципе можно копировать из одного места памяти в другое. Дальше, получить адрес функции в си не проблема - просто указатель на функцию. Остается проблема, как узнать длинну кода занимаемого функцией. Если длинна изместна, то поидее можно копировать в выделенный буфер, например memcpy, ну а далее вызывать по новому указателю... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
makc 195 24 марта, 2005 Опубликовано 24 марта, 2005 · Жалоба Как в C коректнее скопировать функцию из одной области памяти в другую и затем вызвать из нового местоположения. <{POST_SNAPBACK}> Абсолютно корректно это сделать не получится, т.к. этот вопрос не предусмотрен стандартом, но можно сделать следующее: Объявить две функции - копируемую и еще одну, вспомогательную: 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(); но подобный метод накладывает сильные ограничения на то, что может быть написано в копируемой функции. Так, например, если в ней есть вызовы других функций, то необходимо изменить их непосредственные вызовы на вызовы по указателям, переданным вызываемой функции. И т.д. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
olefil 0 24 марта, 2005 Опубликовано 24 марта, 2005 · Жалоба От части этот механизм представлен в оверлеях, когда несколько функций могут занимать одно и то же место в памяти, это решает вопрос маленькой памяти, а копирование кода, точно не к чму не приведет, правда некоторые функции можно переносить таким образом, но только те которые представленны в понятном asm эквиваленте, т.е если там нет каких либо видов оптимизаии и вызовов функции по косвенному смещению от точки вызова. Тут конечно можно примеров много написать чего можно, а чего нельзя, но лучше таких вариантов с кодом не проделывать, а иначе программа может начать вести себя совершенно не вероятным образом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
3.14 0 24 марта, 2005 Опубликовано 24 марта, 2005 · Жалоба 2 max Я правильно понял Ваш пример? Копируемая функция source_f() переносится по адресу функции source_f_end(), вызов пересенной функции осуществляется через pointer() ? Попробовал пример сунуть в VDSP4.0. В дебуггере после memcpy() функция source_f_end() не меняет своего содержимого. В железе все то же виснет :( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
olefil 0 24 марта, 2005 Опубликовано 24 марта, 2005 · Жалоба Компилятор в VDSP может не понимать того, что вы делаете и я больше чем увероен, что это так!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
3.14 0 24 марта, 2005 Опубликовано 24 марта, 2005 · Жалоба 2 olefil Я по большому счету, пытаюсь перенести asm примеры с оверлеями на C. Пока не получается :( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
olefil 0 24 марта, 2005 Опубликовано 24 марта, 2005 · Жалоба А вчем конкретная проблема? Может чем помогу? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
bve 1 24 марта, 2005 Опубликовано 24 марта, 2005 · Жалоба Есть еще одна проблема, зависящая от компилятора и оптимизации - передача параметров в подпрограмму. Т.е. необходимо копировать не только тело самой функции, но и кусок кода ее вызывающий, либо запихивать параметры самому в необходимые регистры/ячейки. Не надо также забывать об изменении указателя фрейма, если таковой имеется. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
makc 195 24 марта, 2005 Опубликовано 24 марта, 2005 · Жалоба 2 max Я правильно понял Ваш пример? Копируемая функция source_f() переносится по адресу функции source_f_end(), вызов пересенной функции осуществляется через pointer() ? Попробовал пример сунуть в VDSP4.0. В дебуггере после memcpy() функция source_f_end() не меняет своего содержимого. В железе все то же виснет :( <{POST_SNAPBACK}> Не совсем так. При решении этой задачи есть две проблемы: 1. Определение размеров копируемой функции. 2. Вызов функции из того места, куда она была скопирована. 1. Для решения этой проблемы вводится функция source_f_end(), которая будет лежать после копируемой функции, т.е. адрес source_f_end - это адрес следующего байта после тела копируемой функции. Таким образом, разность source_f_end - source_f нам даст размер копируемой функции. 2. Функцию копируем в объявленный буфер. Поэтому функция source_f_end и не должна изменить своего содержимого - это только маркер. Буфер для копирования лучше объявить не локальным, а глобальным, тогда будет меньше проблем, т.к. не все процессоры умеют исполнять код из стека. Вызов осуществляется через pointer, значение которого должно быть равно адресу начала буфера, куда была скопирована функция. А что есть в самой копируемой функции? Ведь если там есть прямые вызовы других функций и обращение к глобальным переменным, то она работать не будет. Т.к. как правило их смещения вычисляются линкером при линковке и едут непредсказуемым образом при копировании функции. Может быть в этом проблема? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
makc 195 24 марта, 2005 Опубликовано 24 марта, 2005 · Жалоба Есть еще одна проблема, зависящая от компилятора и оптимизации - передача параметров в подпрограмму. Т.е. необходимо копировать не только тело самой функции, но и кусок кода ее вызывающий, либо запихивать параметры самому в необходимые регистры/ячейки. Не надо также забывать об изменении указателя фрейма, если таковой имеется. <{POST_SNAPBACK}> Минуточку... Есть стандартный способ передачи параметров в подпрограмму, который используется повсеместно (в проекте) одним компилятором. Поэтому нужно иметь правильный прототип функции и тогда вызов будет происходить корректно. Что касается фрейма (я так понимаю, что речь идет о фрейме стека), то он вычисляется исходя из текущего значения указателя стека. А в некоторых случаях он вообще не используется (например у gcc при -fomit-frame-pointer). Так что, как мне кажется, проблемы передачи параметров нет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
olefil 0 24 марта, 2005 Опубликовано 24 марта, 2005 · Жалоба Скорее это так, проблем с передачей параметров действительно нет, но вот от компиляции конкретным оброзом внутренности программы Sharc очень сильно изменяются. И если использовать оптимизацию, то что эта функция делает, знает только компилятор. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
3.14 0 24 марта, 2005 Опубликовано 24 марта, 2005 · Жалоба 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 ??? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sweetin 0 24 марта, 2005 Опубликовано 24 марта, 2005 · Жалоба <Есть стандартный способ передачи параметров в подпрограмму> А в чем он заключается? через general-purpose регистры. а если параметров много - через стековый фрейм функции из которой производится вызов. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
olefil 0 24 марта, 2005 Опубликовано 24 марта, 2005 · Жалоба У меня ща все платы в доработке не фига не попробовать. Но вроде код на первый взгляд правельный. Правда на счет упаковки 48-32 трудно сказать, я сейчас немного другой работой занимаюсь, но вроде похоже на правду. А че показывает VDSP, если в debugger код посмотреть. Блин у меня где-то был исходник для overley'ев копировал функции из внутренней памяти во внешнюю правда не по DMA, а через PX регистр все работало. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться