|
программа на ассемблере |
|
|
|
 |
Ответов
(1 - 12)
|
Jun 5 2008, 09:55
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(dimka76 @ Jun 4 2008, 16:22)  а разве на Си не достаточно перед именем функции написать __famfunc ? "C" - это не только IAR. RVDS, например, вообще не знает что такое __ramfunc. Цитата(dimka76 @ Jun 4 2008, 16:22)  Директива .ORG как раз и говорит линкеру куда размещать следующий за ней код или я не прав? Правильно будет разместить код в определенной секции, а затем указать линкеру, что секция должна быть помещена в область RAM.
|
|
|
|
|
Jun 5 2008, 10:13
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(dimka76 @ Jun 4 2008, 15:22)  а разве на Си не достаточно перед именем функции написать __famfunc ? Директива .ORG как раз и говорит линкеру куда размещать следующий за ней код или я не прав? Рассуждать бессмысленно не зная ни типа процессора ни используемого компилятора/ассемблера/линкера. Обычно директива .ORG задает смещение в текущей секции (а не абсолютный адрес). Адреса начала секций указываются линкеру в его скрипте. __ramfunc, если речь идет об IAR для ARM, указывает линковать код в секцию CODE_I. Скрипт линкера заставляет размещать содержимое секции CODE_I в секцию CODE_ID. Копирование из CODE_ID в CODE_I производит startup-код. Давайте вы для начала признаетесь, о каком компиляторе/ассемблере идет речь и для какого процессора, а еще уточните, как ваша ассемблерная программа будет попадать в ОЗУ.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jun 5 2008, 12:58
|

developer
   
Группа: Свой
Сообщений: 902
Регистрация: 12-04-06
Из: Казань
Пользователь №: 16 032

|
Цитата(Сергей Борщ @ Jun 5 2008, 13:13)  Давайте вы для начала признаетесь, о каком компиляторе/ассемблере идет речь и для какого процессора, а еще уточните, как ваша ассемблерная программа будет попадать в ОЗУ. компилятор IAR C/C++ Compiler for ARM 4.41A Kickstart (4.41.1.301) процессор LPC2103 При функции написании на Си с указанием __ramfunc функция размещается в ОЗУ, а попадает туда при вкл. питания автоматически копируясь из FLASH. По крайней мере я так понял разбираясь с этим типом контроллеров. Кстати, если писать такие фукции на Си( __ramfunc) -> зашиваю контроллер -> работает (дергает ножкой) -> выключаю питание -> включаю питание -> опять работает -> значит образ функции исполняемой из ОЗУ изначально хранится во FLASH и копируется в ОЗУ при вкл. питания. Вот я хочу получить такую же функцию на ассемблере, используя IAR. По поводу директивы .ORG - она задает абсолютный адрес, проверено на практике. И директивы ассемблера, как правило, одинаковы для всех ассемблеров и контроллеров/процессоров. Вот.
--------------------
Все может быть и быть все может, и лишь того не может быть-чего уж точно быть не может, хотя..и это может быть.
|
|
|
|
|
Jun 5 2008, 13:38
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(dimka76 @ Jun 5 2008, 15:58)  Кстати, если писать такие фукции на Си( __ramfunc) -> зашиваю контроллер -> работает (дергает ножкой) -> выключаю питание -> включаю питание -> опять работает -> значит образ функции исполняемой из ОЗУ изначально хранится во FLASH и копируется в ОЗУ при вкл. питания. Да. Но это копирование происходит не "само" каким-то магическим образом, а это делает процедура cstartup. Вы можете убедиться в этом, пройдя программу в симуляторе по шагам от вектора сброса до main(). Цитата(dimka76 @ Jun 5 2008, 15:58)  Вот я хочу получить такую же функцию на ассемблере, используя IAR. Как отдельную законченную программу или как одну из функций С-программы? Если последнее, то напишите в начале вашей функции Код RSEG CODE_I : CODE Если как отдельную программу - то вам придется делать копирование самостоятельно.Сложного там ничего нет, обычный цикл, для получения адресов используйте операторы SFB, SFE, в линкерном скрипте - опцию -Q (посмотрите пример в папках компилятора). Цитата(dimka76 @ Jun 5 2008, 15:58)  По поводу директивы .ORG - она задает абсолютный адрес, проверено на практике. И директивы ассемблера, как правило, одинаковы для всех ассемблеров и контроллеров/процессоров. Вот. Вот? Во-первых, "отучаемся говорить за всех...". Во-вторых, в какой адрес, по-вашему, попадут эти переменные: Код NAME PWM_Data RSEG PWM_DATA : DATA(0) ORG 0
FREQ_0 DS 1 FREQ_1 DS 1 Bitrate DS 1 /* FFSK */ SinStep DS 1 Quadrant DS 1 BitPhase DS 2 ORG SinStep /* GFSK,GMSK */ Curve DS 1 Shifter DS 1 ENDMOD Я утверждаю, что в начало сегмента PWM_DATA. А абсолютный адрес присвоит линкер в процессе размещения секции (проверено на практике  ). В-третьих: По умолчанию ассемблерный файл ассемблируется в абсолютную секцию (см. директиву ASEG). Поэтому если вы не использовали директив переключения секций (RSEG, ASEG, COMMON, STACK), то ваш код попадал в абсолютную секцию, которая начинается с адреса 0 и поэтому результат вашей ORG совпадал с абсолютным адресом.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jun 6 2008, 04:16
|

developer
   
Группа: Свой
Сообщений: 902
Регистрация: 12-04-06
Из: Казань
Пользователь №: 16 032

|
Цитата(Сергей Борщ @ Jun 5 2008, 16:38)  Спасибо . Код RSEG CODE_I : CODE помогло :-) У меня еще один вопросик возник. пишу так с Си файле Код extern void foo(void);
void main(void) { foo(); ... .... } В ассемблерном файле Код MODULE ?foo PUBLIC foo RSEG CODE_I : CODE CODE32
Table1: //всего 255 значений DC32 0 //0 DC32 2 //1 DC32 6 //2 ... ... DC32 1025 //255
Table2: //всего 255 значений DC32 0 //0 DC32 20 //1 DC32 60 //2 ... ... DC32 4025 //255
foo
mov R4,#Table1 mov R8,#Table2
mov PC,LR
ENDMOD END компиляция проходит успешно, а линкер выдает следующие ошибки Код Error[e18]: Range error, Number out of range Where $ = foo + 0x4 [0x40000804] in module "?foo" , offset 0x804 in segment part 0, segment CODE_I What: foo [0x40000000] Allowed range: 0x0 - 0xFF Operand: foo [0x40000000] in module ?foo , Offset 0x0 in segment part 0, segment CODE_I я так подозреваю, что это связано со вторым операндом в строках Код mov R4,#Table1 mov R8,#Table2 Объясните пожалуйста в чем дело?
--------------------
Все может быть и быть все может, и лишь того не может быть-чего уж точно быть не может, хотя..и это может быть.
|
|
|
|
|
Jun 6 2008, 09:24
|

developer
   
Группа: Свой
Сообщений: 902
Регистрация: 12-04-06
Из: Казань
Пользователь №: 16 032

|
поторопился радоваться. Си файл Код extern __ramfunc void foo(void);
UINT data[255] = {1,1,2,3,4,.........,234}; UINT data[255] = {1,2,3,4,....,255};
void main(void) { foo(); } Фсеемблерный файл Код NAME ?foo PUBLIC foo RSEG CODE_I : CODE
foo: mov R1,#10 mov R2,#20 mov PC,LR
ENDMOD END иду по шагам когда программа переходит к метке foo: смотрю дизассемблер и там где должна быть ассемблерная строка расположены нули. в файле линкера ключ -Q вставлен. во FLASH образ функции foo() имеется (смотрю map файл и дизассемблер), но он не переписывается при старте во ОЗУ.
--------------------
Все может быть и быть все может, и лишь того не может быть-чего уж точно быть не может, хотя..и это может быть.
|
|
|
|
|
Jun 6 2008, 09:54
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(dimka76 @ Jun 6 2008, 12:24)  Си файл А текст самой foo - тайна? :-) используйте команду LDR R1, =Table1. Ассемблер сам положит константу с адресом Table1 где-то рядом с этой командой, а саму команду заменит на соответствующий LDR R1, [PC, #N] Цитата(dimka76 @ Jun 6 2008, 12:24)  во FLASH образ функции foo() имеется (смотрю map файл и дизассемблер), но он не переписывается при старте во ОЗУ. А не подключаете ли вы к программе свой cstartup.s79? Если да, то смотрите - есть ли там копирование. Библиотечный стартап копирование выполняет. A!! Есть у них такая штука, как массив в сегменте INITTAB. Его формат следующий: Код /* Structure of an element in the segment initialization table * in segment INITTAB. Used for both zero-initialization and copying. */ typedef struct { long Size; /* Number of bytes to initialize */ char* Dst; /* Destination. If Dst==Src, then init to 0 */ char* Src; /* Source address. Usually in ROM. */ } InitBlock_Type; А дальше библиотечная функция __segment_init(), проходя по этому массиву, делает копирование: Код pragma location="ICODE" __interwork void __segment_init(void) { InitBlock_Type const * const initTableBegin = __sfb( "INITTAB" ); InitBlock_Type const * const initTableEnd = __sfe( "INITTAB" ); InitBlock_Type const * initTableP;
/* Loop over all elements in the initialization table. */ for (initTableP=initTableBegin; initTableP<initTableEnd; initTableP++) { /* If src=dest then we should clear a memory * block, otherwise it's a copy operation. */ if (initTableP->Src == initTableP->Dst) { memset(initTableP->Dst, 0, initTableP->Size); } else { memcpy(initTableP->Dst, initTableP->Src, initTableP->Size); } } } Значит, в вашем ассемблерном файле, вам надо сделать Код RSEG INITTAB:CODE dw ..... dw ..... dw ..... Вот только сразу не соображу - как взять адрес, откуда копировать. Компилятор как-то подставляет, а как тут сделать - ума не приложу. Вот есть кое-что на сайте самого ИАРа. А вот это как раз подходит под ваш случай. Придется заводить свои сегменты  В gcc это сделано более оптимально, без массива.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jun 7 2008, 11:53
|

developer
   
Группа: Свой
Сообщений: 902
Регистрация: 12-04-06
Из: Казань
Пользователь №: 16 032

|
спасибо сергею за подсказки у меня что-то получилось, по крайней мере работает. привожу код который у меня получился в проекте три файла 1. main.c Код #include <iolpc2103.h>
typedef unsigned int UINT; typedef unsigned short USHORT; typedef unsigned char UCHAR;
extern __ramfunc void __haffman(USHORT* pHaff, USHORT* pHaffLen);
USHORT haffman[256] = { 0 , //0 2 , //1 6 , //2 ... 32766 , //254 32767 //255
};
USHORT haffman_len_mask[256] = { 0x0001 , //0 0x0002 , //1 ... 0x4000 //255 };
USHORT* pHaff = haffman; USHORT* pHaffMask = haffman_len_mask;
extern void _cpy(void);
void main() { _cpy(); __haffman(pHaff, pHaffMask); while(1){} } второй сама функция, которая должна выполняться в ОЗУ 2 haff.s79 Код MODULE ?HAFFMAN RSEG RAM_FUNC : CODE PUBLIC __haffman CODE32 DC32 SFB(RAM_FUNC) DC32 SIZEOF(RAM_FUNC) __haffman: //в R0 указатель на первый входной параметр функции // в данном случае указатель на таблицу констант хаффмана // в R1 указатель на второй входной параметр функции // в данном случае указатель на таблицу длинн констант хаффмана mov R2, #35 // data in mov R3,#0x01 // bit position mov R10,#0x40000000 // адресс выходных данных orr R10,R10,#0x1000 mov R11,#0 str R11,[R10] mov R11,#0xFF orr R11,R11,R11, LSL #8 //R11 <- 0x0000FFFF repeat: ldr R4,[R0,R2, LSL #1] //загрузить в R4 код HAFFMAN соответствующий входным данным orr R4,R4,R5,LSL #8 and R4,R4,R11 // маскирование старших 16 бит mul R5,R4,R3 // сдвигаем очередной код на текущую позицию ldr R9,[R10] // загружаем выходные данные из текущей позиции orr R5,R5,R9 // добавляем новые данные str R5,[R0] // сохраняем новые данные cmp R6,#0 addne R0,R0,#4 ldr R7,[R8,R2, LSL #1] //загрузить в R7 длину кода HAFFMAN соответствующий входным данным LSL R7,R7,#1 muls R5,R3,R7 movcs R3, #0x01 movcc R3,R5 addcs R0,R0,#8 b repeat mov PC,LR //возврат из подпрограммы R15 (PC)- программный счетчих, // R14 (LR) - регистр связи в нем автоматически сохраняется // адрес возврата из подпрограммы ENDMOD END и третий файл функция копирования из FLASH в ОЗУ 3 copyd_.s79 Код MODULE ?CPY RSEG CODE_ID : CODE PUBLIC _cpy EXTERN COPYD CODE32 _cpy: ldr R0,COPYD add R5,R0,#4 ldr R1,[R5],#+4 ldr R2,[R5] sub R2,R2,#1 add R0,R0,#4 _cpy_1: ldrb R12,[R0],#+1 subs R2,R2,#1 strb R12,[R1],#+1 bne _cpy_1 mov PC,LR
ENDMOD MODULE ?FLASH RSEG FLASH :CODE PUBLIC COPYD CODE32 COPYD: DC32 SFB(FLASH)
LTORG ENDMOD //?FLASH END и еще подправил файл ххх.XCL в нем убрал Код -QCODE_I=CODE_ID и добавил Код -Z(CODE)RAM_FUNC=40000000-40002000 -Z(CODE)FLASH=40-7FFF
-QRAM_FUNC=FLASH может получилось несколько коряво, но симуляция показывает, что принцип работает. сама функция Код void __haffman(USHORT* pHaff, USHORT* pHaffLen); сырая. я над ней еще работаю поэтому прошу не обращать особого внимания на ее тело а весь проект целиком в прикрепленном файле идея реализации алгоритма Хаффмана взята в подфоруме AVR (необычное использование аппаратного умножителя)
--------------------
Все может быть и быть все может, и лишь того не может быть-чего уж точно быть не может, хотя..и это может быть.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|