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

 
 
5 страниц V  < 1 2 3 4 5 >  
Reply to this topicStart new topic
> Ошибка IAR или чтото еще?
singlskv
сообщение Dec 19 2006, 19:18
Сообщение #31


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



автар
продемонстрируйте свое искуство, так сказать в "малой форме"
Напишите и выложите сюда тестовый исходник и что получаеться в дизассемблере
попробуем разобраться ...
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Dec 19 2006, 19:24
Сообщение #32


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(Sergio66 @ Dec 19 2006, 11:57) *
Был проделан сл эксперимент - формула была упрощена до вида:
long int Local_Value temp = INJ_time * PRODUCTIVITY;
И только...
Результат был неверным! Только размещение в памяти результирующей переменной дало эффект!!!

А говорит ANSI в этом случае? long= long * int.


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
Oldring
сообщение Dec 19 2006, 19:50
Сообщение #33


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



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


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
Sergio66
сообщение Dec 20 2006, 13:33
Сообщение #34


Местный
***

Группа: Свой
Сообщений: 235
Регистрация: 9-02-05
Пользователь №: 2 526



Цитата(Oldring @ Dec 19 2006, 19:50) *
int расширяется до long до умножения. Потом должна вызываться стандартная библиотеченая функция перемножения длинных целых. Потом код самой функции должен скопировать результат из регистров в глобальную переменную. Или не скопировать. Моя уверенность, что это проблема не рассчета, а интерпретации результата, укрепляется. Пожалуй, автору пора научиться разбираться в листингах, порождаемых компилятором.

1. Для тех кто умеет разбираться в листингах - подскажите пожалуйста, как правильно интерпретировать неправильный результат? Если в результате вычислений у меня получается неверное значение, оно же выводится на дисплей, мне придется объяснить пользователям как правильно интерпретировать такой результат который должен быть в пределах от 0,7 до 20, а его зашкаливает за 50 000!!!
2. К сожалению, я не могу выложить всеь код, т.к. это больше 10 000 строк. Одно могу сказать, что данный блок вычислений работал нормально, пока вычисления производились с глобальной переменной. Потом, для экономии памяти я сделал вычисления с локальной. Вот тут то все и началось. Когда компиллятор поместил эту локальную переменную в регистры. Как только я заставил разместить ее в памяти, все заработало.
Go to the top of the page
 
+Quote Post
Oldring
сообщение Dec 20 2006, 14:13
Сообщение #35


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Цитата(Sergio66 @ Dec 20 2006, 13:33) *
1. Для тех кто умеет разбираться в листингах - подскажите пожалуйста, как правильно интерпретировать неправильный результат? Если в результате вычислений у меня получается неверное значение, оно же выводится на дисплей, мне придется объяснить пользователям как правильно интерпретировать такой результат который должен быть в пределах от 0,7 до 20, а его зашкаливает за 50 000!!!


Как какую-то Вашу собственную ошибку, например.

В настройках проекта для ICCAVR включаете на странице List опцию Output list File и отмечаете дополнительные пункты. Компилируете. В листинге находите сбойную функцию, вырезаете кусок текста и публикуете в двух вариантах. Что можно не уметь?


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
_Bill
сообщение Dec 20 2006, 15:06
Сообщение #36


Местный
***

Группа: Участник
Сообщений: 416
Регистрация: 18-04-06
Из: Челябинск
Пользователь №: 16 219



Цитата(Oldring @ Dec 18 2006, 19:08) *
Цитата(Dog Pawlowa @ Dec 18 2006, 18:48) *

Тогда мы по разному понимает слово "правильно". Я включал в это понятие учет возможности переполнения и максимальной независимости от констант. А Вы - нет? smile.gif


Дело в том, что Билл написал просто чепуху про "естественную" свертку целочисленных констант перед вычислением выражения, а Вашего предложения я вообще почему-то не вижу в истории переписки. Так как так и не была озвучена информация про диапазоны операндов, хотелось бы все-таки увидеть, что именно Вы считаете "правильной" записью данного выражения, если это понятие "правильности" отличется от формальной правильности. Хотелось бы также узнать Ваше мнение по следующему вопросу: существует ли с точки зрения стандарта языка программирования С какая-либо разница между выражениями

Код
a * b * c / d


и

Код
((a * b) * c)  / d


?

И, кстати, считаете ли Вы что компилятор имеет право выражение

Код
a = b * 2 / 3;


заменить на

Код
a = 0;


?

Ну, я не думаю, что я написал чепуху. Дело в том, что операция умножения коммутативная операция, а операции умножения и деления имеют одинаковый уровень приоритета. Если взять Ваш пример, то в общем случае совершенно не важно в каком порядке производить вычисления, результат будет один и тот же. То есть
Код
b * c * d / e = (b * c * d) / e = b * c * (d / e)
Проблема возникает именно потому, что появляются типы данных. Компилятор всегда производит перегруппировку выражения таким образом, чтобы код, вычисляющий данное выражения, был минимальным. Если в выражении имеются константы, то компилятор непременно выполнит все возможные вычисления с константами в соответствии с правилами арифметики. По умолчанию все константы имеют тип int, и если их тип не указан особо, то результат также будет иметь тип int. Естественно, что результат вычисления константного выражения может быть неверным, если программист специально об этом не позаботится. В данном случае, операнды d и e будут целыми константами и компилятор обязательно вычислит результат d/e, хотя он в общем случае будет некорректным.
Если мы хотим получить корректный результат, то мы должны задать требуемый порядок вычислений явным образом с помощью скобок. Можно также изменить тип констант по умочанию с использованием соответствующих суффиксов.
Go to the top of the page
 
+Quote Post
Guest_Serg79_*
сообщение Dec 20 2006, 15:22
Сообщение #37





Guests






Sergio66 Ты сдесь воду то не баламуть а приведи нормальный пример своей функции которая у тебя не правельно считает. Что то типа токого:
Код
int my_bad_func(int a, int b, int c)
{
    return a * b / c;
}

А то несешь какую то ахинею типа:
Цитата
Вот такой код:
unsigned long int temp = INJ_time * data_temp_struct.FREQ * PRODUCTIVITY / 20000;
тип INJ_time - unsigned long int. Эта переменная локальная.
PRODUCTIVITY - константа
Так вот, переменная temp размещалась компилятором в регистрах и все было плохо

Теперь я переменную temp сделал членом локальной структуры data_temp_struct
Т.о. она стала размещаться в памяти а не в регистрах. Вот с этого все и заработало.
data_temp_struct.temp = INJ_time * data_temp_struct.FREQ * PRODUCTIVITY / 20000;

Если нашел ошибку то локалезуй ее. И напиши маленькую функцию которая позваляет ее воспроизвести.

А разговоры типа: в регистре не правильно а в памяти правельно, бред сивой кабылы.
Может у Тебя там полнейший бред написан, а Ты пытаешся все на компилятор свалить.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Dec 20 2006, 16:15
Сообщение #38


Гуру
******

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



Пока Sergio66 молчит, задам я свой вопрос, потому как проблема аналогичная. Имеем вот такой код:
Код
.....................

/* время возникновения импульса */
typedef struct
{
   UINT32 Time;  /* время возникновения импульса  */
   UCHAR TIFR_reg; /* сохраненные значения регистра флагов TIFR */

} Pulse_Time_t;
...................................

/*****************************************************************************
Коррекция значения времени
Корректирует время в зависимости от значения TIFR и младшего слова (ТС1)
******************************************************************************/
UINT32 PULSE_SENS_CorrectTime(Pulse_Time_t *Pulse)
{
UINT32 time = Pulse->Time;
  
   /* корректируем результат по состоянию флага OCF1A
    на момент считывания значений времени */
    if(Pulse->TIFR_reg & (1 << OCF1A))
    {
       time += 0x00010000; /* если флаг установлен, инкрементируем значение милисекунд */
       if(SYSTIMER_COMPARE_VAL == LOWORD(time))
        
           /* если значение счетчика равно константе в регистре сравнения, то мы это
           значение должны обнулить */
           time &= 0xffff0000;
    }

    /* преобразуем в мкс (закомментированный код НЕ РАБОТАЕТ )*/
    /* Pulse->Time = ((UINT32)(LOWORD(time) >> 1) + (UINT32)(HIWORD(time)) * 1000); return 0; */
    

    

    return ((UINT32)(LOWORD(time) >> 1) + (UINT32)(HIWORD(time)) * 1000);
}


Кто нибудь может объяснить, почему, когда я возвращаю результат преобразования в микросекунды в структуру Pulse_Time_t, результат в итоге НЕ правильный. Если возвращаю результа из функции - результат Правильный???



2 Serg79 - научитесь изъясняться по-русски, а то Ваше чревовещание больше всего подходит под термин "Бред сивой кобылы" как по грамматическим ошибкам, так и по смыслу…

Бесплатный совет – пишите сообщения сначала в
MS Word – по крайней мере, можно будет подумать, что Вы учили чего-то в школе хотя бы с соседом по парте, а свой букварь курили дома…


--------------------
Go to the top of the page
 
+Quote Post
Oldring
сообщение Dec 20 2006, 16:30
Сообщение #39


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Цитата(_Bill @ Dec 20 2006, 15:06) *
Код
b * c * d / e = (b * c * d) / e = b * c * (d / e)
Естественно, что результат вычисления константного выражения может быть неверным, если программист специально об этом не позаботится. В данном случае, операнды d и e будут целыми константами и компилятор обязательно вычислит результат d/e, хотя он в общем случае будет некорректным.


Чушь. Домыслы.

P.S. Хотел приложить текст стандарта - почему-то не добавился...

Цитата(prottoss @ Dec 20 2006, 16:15) *
НЕ правильный.

Бесплатный совет – пишите сообщения сначала в [/b]MS Word – по крайней мере, можно будет подумать, что Вы учили чего-то в школе хотя бы с соседом по парте, а свой букварь курили дома…


wink.gif


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Dec 20 2006, 17:32
Сообщение #40


Гуру
******

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



Мда... Умные речи о значимости скобок не помогли...
Финал - стоны зрителей, аншлаг, занавес закрывается


--------------------
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Dec 20 2006, 17:54
Сообщение #41


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(prottoss @ Dec 20 2006, 17:32) *
Мда... Умные речи о значимости скобок не помогли...
Финал - стоны зрителей, аншлаг, занавес закрывается

Уличили tongue.gif
А дизассемблер привести сложно? Или мы должны все бросить и посвятить вечер изучению ?
Сами то смотрели?


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
prottoss
сообщение Dec 20 2006, 18:05
Сообщение #42


Гуру
******

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



Цитата(Dog Pawlowa @ Dec 20 2006, 21:54) *
А дизассемблер привести сложно? Или мы должны все бросить и посвятить вечер изучению ? Сами то смотрели?
Я смотрел, и не раз, пожалуйста, c чуйством глубокохо удовлетворения привожу листинг, смотрите:

Код
218          /*****************************************************************************
    219          Коррекция значения времени
    220          Корректирует время в зависимости от значения TIFR и младшего слова (ТС1)
    221          ***************************************************************************
***/
    222          //UINT32 PULSE_SENS_CorrectTime(Pulse_Time_t *Pulse)

   \                                 In segment CODE, align 2, keep-with-next
    223          void PULSE_SENS_CorrectTime(Pulse_Time_t *Pulse)
   \                     PULSE_SENS_CorrectTime:
    224          {
   \   00000000   2F79               MOV     R23, R25
   \   00000002   2E28               MOV     R2, R24
   \   00000004   01F8               MOVW    R31:R30, R17:R16
    225           UINT32 time = Pulse->Time;
   \   00000006   8100               LD      R16, Z
   \   00000008   8111               LDD     R17, Z+1
   \   0000000A   8122               LDD     R18, Z+2
   \   0000000C   8133               LDD     R19, Z+3
    226            
    227             /* корректируем результат по состоянию флага OCF1A
    228              на момент считывания значений времени */
    229              if(Pulse->TIFR_reg & (1 << OCF1A))
   \   0000000E   8144               LDD     R20, Z+4
   \   00000010   FF44               SBRS    R20, 4
   \   00000012   C00A               RJMP    ??PULSE_SENS_CorrectTime_0
    230              {
    231                 time += 0x00010000; /* если флаг установлен, инкрементируем значение милисекунд */
   \   00000014   5000               SUBI    R16, 0
   \   00000016   4010               SBCI    R17, 0
   \   00000018   4F2F               SBCI    R18, 255
   \   0000001A   4F3F               SBCI    R19, 255
    232                 if(SYSTIMER_COMPARE_VAL == LOWORD(time))
   \   0000001C   2F51               MOV     R21, R17
   \   0000001E   3C0F               CPI     R16, 207
   \   00000020   4057               SBCI    R21, 7
   \   00000022   F411               BRNE    ??PULSE_SENS_CorrectTime_0
    233                  
    234                     /* если значение счетчика равно константе в регистре сравнения, то мы это
    235                     значение должны обнулить */
    236                     time &= 0xffff0000;
   \   00000024   E000               LDI     R16, 0
   \   00000026   E010               LDI     R17, 0
    237              }
    238          
    239              /* преобразуем в мкс */
    240              Pulse->Time = ((UINT32)(LOWORD(time) >> 1) + (UINT32)(HIWORD(time)) * 1000);
   \                     ??PULSE_SENS_CorrectTime_0:
   \   00000028   01A8               MOVW    R21:R20, R17:R16
   \   0000002A   9556               LSR     R21
   \   0000002C   9547               ROR     R20
   \   0000002E   E060               LDI     R22, 0
   \   00000030   0189               MOVW    R17:R16, R19:R18
   \   00000032   01C8               MOVW    R25:R24, R17:R16
   \   00000034   EE08               LDI     R16, 232
   \   00000036   E013               LDI     R17, 3
   \   00000038   E020               LDI     R18, 0
   \   0000003A   E030               LDI     R19, 0
   \   0000003C   9F19               MUL     R17, R25
   \   0000003E   0D20               ADD     R18, R0
   \   00000040   1D31               ADC     R19, R1
   \   00000042   9F18               MUL     R17, R24
   \   00000044   2D10               MOV     R17, R0
   \   00000046   0D21               ADD     R18, R1
   \   00000048   1F36               ADC     R19, R22
   \   0000004A   9F09               MUL     R16, R25
   \   0000004C   0D10               ADD     R17, R0
   \   0000004E   1D21               ADC     R18, R1
   \   00000050   1F36               ADC     R19, R22
   \   00000052   9F08               MUL     R16, R24
   \   00000054   2D00               MOV     R16, R0
   \   00000056   0D11               ADD     R17, R1
   \   00000058   1F26               ADC     R18, R22
   \   0000005A   1F36               ADC     R19, R22
   \   0000005C   0F04               ADD     R16, R20
   \   0000005E   1F15               ADC     R17, R21
   \   00000060   1F26               ADC     R18, R22
   \   00000062   1F36               ADC     R19, R22
   \   00000064   8300               ST      Z, R16
   \   00000066   8311               STD     Z+1, R17
   \   00000068   8322               STD     Z+2, R18
   \   0000006A   8333               STD     Z+3, R19
    241              //return ((UINT32)(LOWORD(time) >> 1) + (UINT32)(HIWORD(time)) * 1000);
    242          }
   \   0000006C   2D82               MOV     R24, R2
   \   0000006E   2F97               MOV     R25, R23
   \   00000070   9508               RET




Что бы не напрягать попусту Ваши глаза и мозговые извилины, сделаю два замечания:

В начале кода компилятор послушно берет адрес и формирует переменную time из регистров r16-19
Код
00000000   2F79               MOV     R23, R25
   \   00000002   2E28               MOV     R2, R24
   \   00000004   01F8               MOVW    R31:R30, R17:R16
    225           UINT32 time = Pulse->Time;
   \   00000006   8100               LD      R16, Z
   \   00000008   8111               LDD     R17, Z+1
   \   0000000A   8122               LDD     R18, Z+2
   \   0000000C   8133               LDD     R19, Z+3


В конце, так же послушно запихивает то, что пережевал обратно:

Код
   \   00000064   8300               ST      Z, R16
   \   00000066   8311               STD     Z+1, R17
   \   00000068   8322               STD     Z+2, R18
   \   0000006A   8333               STD     Z+3, R19


Что и как он там насчитал, меня мало интересует, но факт остается фактом, насчитал он не правильно


--------------------
Go to the top of the page
 
+Quote Post
Oldring
сообщение Dec 20 2006, 18:57
Сообщение #43


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Чтобы не напрягать попусту наши извилины скомпилируйте теперь второй вариант и найдите отличия.

И, кстати, это так ведь задумано - при каждом вызове функции портить Pulse->Time?


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Dec 20 2006, 19:12
Сообщение #44


Гуру
******

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



Цитата(Oldring @ Dec 20 2006, 22:57) *
Чтобы не напрягать попусту наши извилины скомпилируйте теперь второй вариант и найдите отличия.
И, кстати, это так ведь задумано - при каждом вызове функции портить Pulse->Time?
Именно так и задуманно, с целью сэконмить несколько десятков байт памяти программ и несколько сотен наносекунд процессорного времени. Винигрет из команд MUL, MOV, ADD, ADC абсолютно одинаковый, за исключением того, что поменены функции регистровых пар R21:20 и R25:24 в "правильно работающем варианте". Возможно ошибка в этом, а возможно еще в чем то. НО, простите, нахрена я пишу на Си, чтобы потом перелопачивать этот же код на ассемблере?

Думаю, что у Sergio66 аналогичная проблема. Возможно, это связанно именно с типом LONG... Кстати, я пользуюсь IAR v.4.10B а Sergio66 IAR v.4.20.


--------------------
Go to the top of the page
 
+Quote Post
Oldring
сообщение Dec 20 2006, 19:19
Сообщение #45


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Замечательно, где еще прописывается значение Pulse->Time и как часто вызывается эта функция?

И уж выложите пожалуйста "правильный" вариант.


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post

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

 


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


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