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

 
 
5 страниц V  < 1 2 3 4 > »   
Reply to this topicStart new topic
> Сопоставление проектов С и АСМ, Немного цифр
SasaVitebsk
сообщение Feb 19 2008, 11:42
Сообщение #16


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Цитата(Т.Достоевский @ Feb 19 2008, 03:25) *
ИМХО. Написать С код соизмеримый с асмом можно, но требует таких же трудозатрат.


А вы анализировали глобально производительность программы в процессе оптимизации? Существует теория оптимизации (естественно).

Если исключить оптимизацию по коду (в большенстве случаев удобнее просто другой чип взять), а брать оптимизацию по скорости, то возникает следующая ситуация. Оптимизировать требуется только незначительную часть кода. Обычно - единицы процентов. Это даёт существенный результат. Оптимизация же остальной части сказывается не сильно.

Опыт показывает, что оптимизировать этот кусочек лучше именно в виде "подсказок" для компилятора. У меня это дало практически идеальный код. потери в сравнении с асмом - 5% не больше. К сожалению, такая оптимизация тоже получается (CPU-зависима). Выработав некоторые общие принципы, можно сразу писать так, что будет код очень эффективный.

Вот пример
Код
void Point(uint8_t X,uint8_t Y,uint8_t Color)            // Вывести точку
{
uint8_t    maska;                                        // Смещение    относительно байта
uint8_t    *addr;                                        // Адрес экраного байта

maska =0x3;
if((X & 2)==0)
{
   maska = 0x30;
   Color <<= 4;
}
if((X & 1)==0)
{
   maska <<=2;
   Color <<=2;
}
maska = ~maska;
if(NEkr>0) addr = &Ekr[SIZE_EKR];
else addr = Ekr;

addr += (Y*SizeXb)+(X>>2);
maska &= *addr;
maska += Color;
*addr = maska;
}
/*offset    = (X & 3) << 1;                                // выделить    смещение точки в байте
maska = ~(3<<offset);
addr = (Y*SizeXb)+(X>>2);
maska &= Ekr[NEkr][addr];
maska += Color << offset;
Ekr[NEkr][addr] = maska;
}*/

Результат - двукратный рост производительности.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Feb 19 2008, 12:04
Сообщение #17


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(SasaVitebsk @ Feb 19 2008, 14:42) *
Вот пример

Ну, я бы еще для масок завел массив в памяти программ, но, не видя листинга, могу и ошибиться.
Go to the top of the page
 
+Quote Post
forever failure
сообщение Feb 19 2008, 13:13
Сообщение #18


Местный
***

Группа: Участник
Сообщений: 256
Регистрация: 6-03-05
Из: Екатеринбург
Пользователь №: 3 112



Цитата(SasaVitebsk @ Feb 19 2008, 16:42) *
Результат - двукратный рост производительности.

И можно ещё быстрее и компактней...
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Feb 19 2008, 17:00
Сообщение #19


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Цитата(forever failure @ Feb 19 2008, 17:13) *
И можно ещё быстрее и компактней...

Наверняка.
В данном примере просто наглядно видно что я вместо вызова п/п сдвига на N бит делаю анализ указателя сдвига с генерацией констант.

Табличный метод в данном месте хуже.
вот кусочек результирующего листинга
Код
    891           if(chBright<0)
   \   00000004   2322               TST     R18
   \   00000006   F422               BRPL    ??PointB_0
    892           {
    893             ColorX =0;
   \   00000008   E030               LDI     R19, 0
    894             ch = -chBright;
   \   0000000A   2F02               MOV     R16, R18
   \   0000000C   9501               NEG     R16
   \   0000000E   C002               RJMP    ??PointB_1
    895           }
    896           else
    897           {
    898             ColorX =3;
   \                     ??PointB_0:
   \   00000010   E033               LDI     R19, 3
    899             ch = chBright;
   \   00000012   2F02               MOV     R16, R18
    900           }
    901           maska =0x3;
   \                     ??PointB_1:
   \   00000014   E023               LDI     R18, 3
    902           if((X & 2)==0)
   \   00000016   FB41               BST     R20, 1
   \   00000018   F02E               BRTS    ??PointB_2
    903           {
    904             maska = 0x30;
   \   0000001A   E320               LDI     R18, 48
    905             ColorX <<= 4;
   \   0000001C   9532               SWAP    R19
   \   0000001E   7F30               ANDI    R19, 0xF0
    906             ch <<= 4;
   \   00000020   9502               SWAP    R16
   \   00000022   7F00               ANDI    R16, 0xF0
    907           }

Как видим вполне прилично. На асме у меня получился выигрыш в несколько тактов.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Feb 20 2008, 08:15
Сообщение #20


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Теперь немного о другом. Рискую утомить читателя, поэтому-кратко.
0. Код под Winavr

1. В EEPROM имеется несколько наборов параметров, активный набор обозначен селектором:

Код
uint8_t EEMEM Selector=0x00;

#define Max_Applicable_Paramsets 4
typedef struct {
    uint16_t Cap_Chg_Time;         // ==0 then continuous mode
    uint16_t Cap_Charge_Volt;     // chg to volt
    uint16_t Cap_Discharge_Volt;     // disch downto this value (volts)
    uint16_t Operating_Current;    // ==0 then voltage mode
    uint8_t     Amplitude;        // used for voltage mode boost
    uint16_t PWMfreq;
    uint16_t Expose_Time;        // in 10ms step
    uint8_t  Rly_Mode;        // ==0 none rly is turned on at selection

    } App_Param_Record;
// eeprom implementation
App_Param_Record EEMEM Parameter_set[Max_Applicable_Paramsets] =
{{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0}};


2. В памяти программ есть дескрипторы этих параметров, но только для активной страницы

Код
//дескриптор параметра
typedef struct {
                      uint8_t xcmd; // параметр соответствует некоторой команде, получаемой извне
                      void *ojaddr; // адрес параметра
                      uint8_t ojsize;// размер данных+ здесь же добавил опции размещения (см ниже) этих данных
                     } Cm_Xref_;

typedef Cm_Xref_ PROGMEM Cm_Xref_t; // объявили
// опции размещения данных
#define Fitter_mask 0xC0
// размещено во флеше (т.е. данные будут только для чтения)
#define Flash_Fit 0x80
// размещено ЕЕ
#define EE_Fit 0xC0
// размещено в ОЗУ и только для чтения
#define Sram_Fit_RO 0x40  //fitted in sram and read only

// Размещено в буфере типа  App_Param_Record, в который будет копироваться страница параметров
#define Relative_Fit 0x00 // relative to struct

// Команды на чтение 0x00..0x7F на запись 0x80..0xFF
#define Inhibit_read_write_mask 0x7F

//собсно описания

static App_Param_Record Edited_Record; // sram shadow

#define Rel_Param(member) &Edited_Record.member,Relative_Fit+sizeof(Edited_Record.member)

static Cm_Xref_t Cm_Xref[Max_cmd+1]=
{
    {cm_Brief,0,0}, // version crc
    {cm_NetLocate,&Net_ID,EE_Fit+1},
    {cm_Set_Selector,&Selector,EE_Fit+1},
    {cm_Charge_Time,Rel_Param(Cap_Chg_Time)},
    {cm_Charge_Volt,Rel_Param(Cap_Charge_Volt)},
    {cm_Discharge_Volt,Rel_Param(Cap_Discharge_Volt)},
    {cm_Operating_Current,Rel_Param(Operating_Current)},
    {cm_Amplitude,Rel_Param(Amplitude) },
    {cm_Expose_Time,Rel_Param(Expose_Time)},
    {cm_Rly_Mode,Rel_Param(Rly_Mode)}
};


Сложняк ?
Да. Для описания параметров из активной страницы пришлось принять, что эту страницу мы будем копировать в буфер. По-другому никак. Потому что, иначе мы разрушаем переносимость программы.

3. Проглотил я, короче, эти сложности - в конце концов памяти программ я пока не потерял.
В общем, дело доходит до реализации. Обрезал я поиск команды. Оставил обращение типа Cm_Xref[command].
Привожу процедуру без купюр и особых комментов. Все названия сторонних функций - сами за себя говорят.

Код
void Track_Pult(void)
{
uint8_t buffer[8],Rsz,*addr,k;
Packet_Layout *pack;
Cm_Xref_ xref,*xr;

    Rsz = RS485_pack_ready();
    if (!Rsz) return;
    // <datasize> <receiver> <sender> <command> <data> <crc>
    pack = &RS_buff;

        if((pack->receiver) != Get_Net_ID()) goto Catch;

    // else -continue parsing received pack
    Sender_Addr = pack->sender;// store sender
    Rsz -= 5;


           k = pack->command & Inhibit_read_write_mask;

    if (k == cm_Remote_Start){
      Set_Start_Status();
      Send_error(er_OK); // :) no errors
      goto Catch; }

    if (k == cm_Remote_Stop) {
      Set_Stop_Status();
      Send_error(er_OK);
      goto Catch; }

    if (k >= Max_cmd) {Send_error(er_Unknown_cmd);goto Catch;}

        xr = memcpy_P(&xref,&(Cm_Xref[k]),sizeof(xref));

uint8_t options,objsize;
void *compaddr;

    options = xref.ojsize;
    objsize = options & (~Fitter_mask);
    options &= Fitter_mask;
    addr = xref.ojaddr;
    k = pack->command != k;
    if (Dev_Status.IsWorking) {Send_error(er_Busy); goto Catch;}
    if (Rsz != objsize) {Send_error(er_InvParam); goto Catch;}

    switch (options){
    case Flash_Fit:
        if (k) Send_error(er_Read_Only);
        else   Send_data(er_OK,memcpy_P(&buffer,addr,objsize),objsize);
        break;

    case EE_Fit:
        eeprom_read_block(&buffer,addr,objsize);
        if (k) {eeprom_write_block(addr,&(pack->data),objsize);Send_error(er_OK);}
         else Send_data(er_OK,&buffer,objsize);
        break;
    case Relative_Fit:
        compaddr = Paramset();
        eeprom_read_block(&Edited_Record,compaddr,sizeof(Edited_Record));
        if (k) {eeprom_write_block(&Edited_Record,compaddr,sizeof(Edited_Record)); Send_error(er_OK);}
            else Send_data(er_OK, addr,objsize);
        break;

        }
Catch:
    RS485_purge_received();
    return;
}


Утомил?
Могу сказать одно - на асме эта байда была бы существенно проще. Я уже не говорю про смысл записи в EEPROM значений, которые не изменились. smile.gif Если я еще чего туда наверну, мне памяти точно не хватит.
Если все-же кто-то "асилил" то, что я накрапал, подскажите, как бороться со сложняком в системе описания параметров. Через "C", ессно.
З.Ы. О цифрах забыл размер кода 364 байт. Время - пофиг. Оптимизация -Os
З.З.Ы. Подчистил грязь - исправил "caller" на "receiver"
Go to the top of the page
 
+Quote Post
defunct
сообщение Feb 20 2008, 14:51
Сообщение #21


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(_Pasha @ Feb 20 2008, 10:15) *
Могу сказать одно - на асме эта байда была бы существенно проще. Я уже не говорю про смысл записи в EEPROM значений, которые не изменились. smile.gif

Стиль значит асмовый используется.. Попробуйте писАть на С, а не на asm сишными словами.
Одинаковые значения в eeprom тоже никто не заставляет писать, в функции записи байта сделать вычитку ячейки, совпадает с тем что пишем - выход.
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Feb 20 2008, 16:25
Сообщение #22


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Не могу сказать, что я точно понял смысл, но попробую. Хотя если из другой оперы - то извиняй. (Мне кажется я делал что-то подобное)

1. Все команды строю однотипно типа так.
Код
struct AddrKomXx
{
uint8_t            Name;                    // Имя команды
uint16_t            TimeStart;                // Время начала исполнения команды
} *KomXx;

struct AddrKomC
{
uint8_t            Name;                    // Имя команды
uint16_t             TimeStart;                // Время начала исполнения команды
uint8_t             TimeMashtabTek,            // Текущее значение масштаба для времени исполнения
                    TimeMashtab;            // Масштаб для времени исполнения
uint16_t            TimeLife;                // Время исполнения команды с учётом масштаба
int16_t             BegX,BegY,                // Начало объекта (X,Y)
                    SizeX,SizeY;            // Размеры объекта (X,Y)
int8_t                VecX,VecY;                // вектор перемещения объекта (X,Y)
uint8_t            color;                    // цвет заливки
} *KomC;

struct AddrKomK
{
uint8_t            Name;                    // Имя команды
uint16_t             TimeStart;                // Время начала исполнения команды
uint8_t             KernTek;                 // Текущее значение масштаба для времени исполнения
} *KomK;


У меня их море, это кусочек. Причём первая AddrKomXx это несуществующая "виртуальная", для определения текущей. Определение делаю так.
Код
  KomXx    = (struct AddrKomXx*) AdrActiveKom[i];            // Прочитать адрес текущей активной    команды
  if(KomXx->TimeStart>Status.TekTime) continue;            // Если    не подошло время для исполнения    команды, то    пропустить данную команду
  switch (KomXx->Name) {
  /* Команда "END" - "Ролик    завершить" */
  case 'S':
  /* Команда "Stop-Kadr"    - "Остановить модификацию картинки" */
            KomS = (struct AddrKomS*) AdrActiveKom[i];    // Прочитать адрес текущей активной    команды
...

То есть сначала адрес начала команды "сопоставляю" с "виртуальной" командой все поля в которой в точности совпадают во всех командах и по ней осуществляю контроль команды, а потом "пересопоставляю" с уже реальной командой, где уже реальные поля и работаю с ней.
Если работаешь с сылками(адресами), как я, то без разницы где находится команда и её можно не пересылать вообще. Имей один буфер приёма - с ним и работай. Я например даже удаляю отработавшие и делаю "сборку мусора". zltigo ещё интереснее сделал, если я подосвобожусь тоже так попробую - он свой диспетчер кучи написал и работает с занятием/освобождением весьма грамотно. У меня, принципиально, возможны проколы в данном месте - я это знаю.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Feb 20 2008, 18:49
Сообщение #23


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(defunct @ Feb 20 2008, 17:51) *
Стиль значит асмовый используется.. Попробуйте писАть на С, а не на asm сишными словами.
Одинаковые значения в eeprom тоже никто не заставляет писать, в функции записи байта сделать вычитку ячейки, совпадает с тем что пишем - выход.

1. Дописываю тот же кусок кода на асме. Для сравнения. Получается в полновесном варианте, со всеми обработками ошибок, с поиском правильной команды и с таблицей - меньше 200 байт. Завтра выложу в аттаче, дабы не превращать тему в "кодовый флуд". По поводу "писАть на С" - я "С" терпеть не могу еще с 1992 года smile.gif Проблемы-то начинаются с обращения к памяти программ за данными. Этот процесс нигде не автоматизирован, отсюда сложности.
2. Переопределять стандартные функции НЕ ХОЧУ.

Цитата(SasaVitebsk @ Feb 20 2008, 19:25) *
Не могу сказать, что я точно понял смысл, но попробую. Хотя если из другой оперы - то извиняй. (Мне кажется я делал что-то подобное)

Смысл: Хранение в девайсе настроечных параметров и обращение к ним, например, через команды по последовательному порту.

Цитата
... он свой диспетчер кучи написал и работает с занятием/освобождением весьма грамотно. У меня, принципиально, возможны проколы в данном месте - я это знаю.

Вот! Там, где дело касается ОЗУ - ессно "С" выиграет.
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Feb 20 2008, 21:06
Сообщение #24


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Цитата(_Pasha @ Feb 20 2008, 22:49) *
Проблемы-то начинаются с обращения к памяти программ за данными. Этот процесс нигде не автоматизирован, отсюда сложности.
2. Переопределять стандартные функции НЕ ХОЧУ.
Смысл: Хранение в девайсе настроечных параметров и обращение к ним, например, через команды по последовательному порту.
Вот! Там, где дело касается ОЗУ - ессно "С" выиграет.

Никаких проблем при обращении к памяти программ за данными я не заметил. Обращаешься так же как и к обычной переменной. Более того код получается очень эффективным. Пересылать абсолютно ничего не надо. По крайней мере в IAR.
В редких случаях, когда идут разнотипные данные компилятору приходится явно указывать что идёт обращение к flash.
Например
Код
// Знакогенераторы
const    void    __flash   *symbol[MAX_FONTS] = {&fnt0_6x8,&fnt1_8x8,&fnt2_10x10,&fnt3_11x13,&fnt4_9x14,&fnt5_16x16,&fnt6_16x16,&fnt7_12x13,&fnt8_16x15,&fnt9_14x16};
....
uint8_t __flash  *addr;
.....
     addr =    ((uint8_t __flash *)symbol[tekfonts])+(Znak*Fonts[tekfonts][1]);
.....

А обычно и этого делать не приходится
Код
// структура данных по символам
struct CharZnak
{
uint16_t            sm;                        // Смещение от начала фонта
uint8_t            width;                    // Ширина символа
};

//extern             uint16_t                __checksum;        //    CHECKSUM;
//const __flash    uint16_t                EndFlashAdr @0xe5 = & __checksum;

extern const    uint8_t        __flash        Fonts[MAX_FONTS][2];
extern const __flash struct    CharZnak    struct_fnt[MAX_FONTS-2][223];
....
    symbolx=struct_fnt[tekfonts-2][Znak].width + tekkern;


Вот пример компиляции
Код
   1038              symbolx=struct_fnt[tekfonts-2][Znak].width + tekkern;
   \   0000002C   ....               LDI     R30, LOW((struct_fnt - 1336))
   \   0000002E   ....               LDI     R31, HIGH((struct_fnt - 1336))
   \   00000030   5221               SUBI    R18, 33
   \   00000032   E003               LDI     R16, 3
   \   00000034   9F02               MUL     R16, R18
   \   00000036   0DE0               ADD     R30, R0
   \   00000038   1DF1               ADC     R31, R1
   \   0000003A   E90D               LDI     R16, 157
   \   0000003C   E012               LDI     R17, 2
   \   0000003E   9F14               MUL     R17, R20
   \   00000040   2D10               MOV     R17, R0
   \   00000042   9F04               MUL     R16, R20
   \   00000044   0D11               ADD     R17, R1
   \   00000046   0DE0               ADD     R30, R0
   \   00000048   1FF1               ADC     R31, R17
   \   0000004A   9104               LPM     R16, Z
   \   0000004C   0F06               ADD     R16, R22
   \                     ??ZnakWidth_1:
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Feb 21 2008, 01:19
Сообщение #25


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Вот это совсем другое дело! smile.gif
Че-то WINAVR тормозит немного. А может я торможу - начитался мануалов, а уже все работает. Пойду проверю.
Насчет диспетчера кучи: я так понял, надо либо собрать все указатели, работающие с выделяемыми объектами, в одну секцию. Тогда при дефрагментации памяти сравнительно легко все перемещается. Либо не париться и держать дескрипторы.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Feb 21 2008, 07:20
Сообщение #26


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(_Pasha @ Feb 21 2008, 06:19) *
Вот это совсем другое дело! smile.gif
Че-то WINAVR тормозит немного.


WINAVR как раз в этом очень сильно тормозит. Работа с флешом в нём сделана мегакриво. Так как в примере SasaVitebsk-а, не выйдет.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Feb 21 2008, 07:34
Сообщение #27


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(AHTOXA @ Feb 21 2008, 10:20) *
WINAVR как раз в этом очень сильно тормозит. Работа с флешом в нём сделана мегакриво.

... И похоже, что по политическим соображениям никогда не исправится.
Насчет кривизны:
Из предыдущего утомительного примера:
Код
static Cm_Xref_t Cm_Xref[Max_cmd+1]=
{
    {cm_Brief,0,0}, // version crc
    {cm_NetLocate,&Net_ID,EE_Fit+1},
    {cm_Set_Selector,&Selector,EE_Fit+1},
/*****************************************/
};
/******************************************/
uint8_t M;
M = Cm_Xref[2].ojsize;


Так constant propagation оно просчитывает. А стоит появиться адресному выражению - кирдык.
Цитата
Попробуйте писАть на С, а не на asm сишными словами...


Блин, вот зацепил...до сих пор помню.
Go to the top of the page
 
+Quote Post
ReAl
сообщение Feb 21 2008, 08:43
Сообщение #28


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(_Pasha @ Feb 21 2008, 03:19) *
Вот это совсем другое дело! smile.gif
Че-то WINAVR тормозит немного.

Ну, у avr-gcc код как правило похуже, с этим не спорю.
Код
#include <stdint.h>
#include <avr/pgmspace.h>
#define MAX_FONTS 10 // от балды, в приведеннмо примере не было задано. Но оно неважно

// структура данных по символам
struct CharZnak
{
uint16_t            sm;                        // Смещение от начала фонта
uint8_t            width;                    // Ширина символа
};

extern const  uint8_t   Fonts[MAX_FONTS][2] PROGMEM;
extern const  struct    CharZnak    struct_fnt[MAX_FONTS-2][223] PROGMEM;
extern uint8_t tekfonts, tekkern;

uint8_t sx(uint8_t Znak)
{
    return pgm_read_byte( & struct_fnt[tekfonts-2][Znak].width ) + tekkern;
}


CODE
.file "tst.c"
__SREG__ = 0x3f
__SP_H__ = 0x3e
__SP_L__ = 0x3d
__tmp_reg__ = 0
__zero_reg__ = 1
.global __do_copy_data
.global __do_clear_bss
.text
.global sx
.type sx, @function
sx:
/* prologue: frame size=0 */
/* prologue end (size=0) */
ldi r25,lo8(3)
mul r24,r25
movw r30,r0
clr r1
lds r24,tekfonts
ldi r25,lo8(0)
ldi r18,lo8(669)
ldi r19,hi8(669)
movw r20,r24
mul r20,r18
movw r24,r0
mul r20,r19
add r25,r0
mul r21,r18
add r25,r0
clr r1
add r30,r24
adc r31,r25
subi r30,lo8(-(struct_fnt-1336))
sbci r31,hi8(-(struct_fnt-1336))
/* #APP */
lpm r30, Z
/* #NOAPP */
lds r24,tekkern
add r30,r24
mov r24,r30
ldi r25,lo8(0)
/* epilogue: frame size=0 */
ret
/* epilogue end (size=1) */
/* function sx size 31 (30) */
.size sx, .-sx
/* File "tst.c": code 31 = 0x001f ( 30), prologues 0, epilogues 1 */

Катастрофической я бы разницу не назвал - ни в написании текста, ни в сгенерированном коде.
Сравнивать надо одинаковые фрагменты, в приведенном выше куске часть регистров уже "откуда ни возьмись" заполнены и используются, тут всё "автономно".


Цитата(_Pasha @ Feb 20 2008, 20:49) *
По поводу "писАть на С" - я "С" терпеть не могу еще с 1992 года smile.gif
Я года с 1987..88 использую и ничего. Что-то писалось чисто асмовое, что-то с делением "это пусть на С, а эта часть на асме".
Сейчас если очень хочется - пишу вставку на асме. В последнее время хочется всё реже.

Цитата
2. Переопределять стандартные функции НЕ ХОЧУ.
Ну извините... Так можно дойти до "а на асме я могу что-то другое делать, пока EEPROM пишется, а С-шная программа станет колом на всё время записи блока, во какой плохой язык С".
И начать требоавть стандартную функцию для решения всей своей задачи.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
defunct
сообщение Feb 21 2008, 11:52
Сообщение #29


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(_Pasha @ Feb 21 2008, 09:34) *
Блин, вот зацепил...до сих пор помню.

С одной стороны это гут, т.к. хотел обратить Ваше внимание на то, что стиль кода Вашего примера не Сишный, и рад что вышло. Все тоже самое в Сишном стиле можно сделать красивее и быстрее чем на асм, и уже глядя на код нельзя будет его назвать "байдой".

Цитата
Проблемы-то начинаются с обращения к памяти программ за данными. Этот процесс нигде не автоматизирован, отсюда сложности.

да и на асм он не автоматизирован, ровно в той же степени.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Feb 21 2008, 16:57
Сообщение #30


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Вернемся к нашей баранине. "Не умеешь-научим, не хочешь-заставим." Заставили. Дописал функцию записи в ЕЕПРОМ, в аккурат по шаблону eeprom_write_block() .

Код
void EE_Proof_Write_Block(const void *pointer_ram,
              void *pointer_eeprom,
              size_t n)
{
size_t j;
uint8_t *src,*dst;

src = (uint8_t*)pointer_ram;
dst = (uint8_t*)pointer_eeprom;

for (j=0;j<n;j++)
{
  if (eeprom_read_byte(dst) != *src)
      eeprom_write_byte(dst,(uint8_t)*src);
  dst++;
  src++;
}
return;
}


ИТОГО такое: +56 байт. Имея ввиду, что была исходная eeprom_write_block(), вычтем, скажем, байт 16. В добавок, это все можно обрезать, задаваясь размером блока не size_t a uint8_t, если уж очень хотца. Это еще минус байта 4-6. Короче, +32..36 байт. Оптимайзер рулит!!!
Может, мы доживем до тех времен, когда свопинг лишний чистится будет...
Кстати, кто-нибудь знает, почему многопроходовая оптимизация в GCC не в фаворе?

Цитата(defunct @ Feb 21 2008, 14:52) *
Все тоже самое в Сишном стиле можно сделать красивее и быстрее чем на асм, и уже глядя на код нельзя будет его назвать "байдой".


Боюсь, что не получится. Команд будет поболее - до 30 в полновесном варианте. И надо, чтобы в идеале доступ был не по индексу, а по LookUp, т.к. коды команд могут меняться. Так что от таблицы никуда не денешься. Впрочем, если Вы пальцем ткнете, я пойму, что имеется ввиду...
Go to the top of the page
 
+Quote Post

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

 


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


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