Гадкий компилятор

Тема в разделе "WASM.ASSEMBLER", создана пользователем mha, 6 май 2006.

  1. mha

    mha New Member

    Публикаций:
    0
    Регистрация:
    4 май 2006
    Сообщения:
    6
    Пишу в среде CodeWarrior для контроллеров freescale HC(S)



    Есть макрос

    #define EnableMC13192Timer1(u32Timeout) \

    SPIDrvWrite(0x1B,(UINT16)((u32Timeout >>16) &0x000000FF) |0x000080FF); \

    SPIDrvWrite(0x1C,(UINT16)( u32Timeout &0x0000FFFF)); \

    SPIDrvWrite(0x1B,(UINT16)((u32Timeout >>16) &0x000000FF)); \

    SPIDrvWrite(0x1C,(UINT16)( u32Timeout &0x0000FFFF));



    Есть константы

    #define NUMBER_OF_SENSORS 2

    #define TIMEOUT_TO_SENSORS 30000



    Вызываю макрос

    1)EnableMC13192Timer1(60000);

    2)EnableMC13192Timer1(NUMBER_OF_SENSORS*TIMEOUT_TO_SENSORS);



    В первом случае все работает и компилятор выдает

    0073 a61b LDA #27

    0075 4580ff LDHX #-32513

    0078 cd0000 JSR SPIDrvWrite

    007b a61c LDA #28

    007d 45ea60 LDHX #-5536

    0080 cd0000 JSR SPIDrvWrite

    0083 a61b LDA #27

    0085 5f CLRX

    0086 8c CLRH

    0087 cd0000 JSR SPIDrvWrite

    008a ae60 LDX #96

    008c a6ea LDA #-22

    008e 87 PSHA

    008f 8a PULH

    0090 a61c LDA #28

    0092 cd0000 JSR SPIDrvWrite

    Во втором случае не работает и получаю

    0073 a61b LDA #27

    0075 4580ff LDHX #-32513

    0078 cd0000 JSR SPIDrvWrite

    007b a61c LDA #28

    007d 45ea60 LDHX #-5536

    0080 cd0000 JSR SPIDrvWrite

    0083 a61b LDA #27

    0085 aeff LDX #-1

    0087 8c CLRH

    0088 cd0000 JSR SPIDrvWrite

    008b ae60 LDX #96

    008d a6ea LDA #-22

    008f 87 PSHA

    0090 8a PULH

    0091 a61c LDA #28

    0093 cd0000 JSR SPIDrvWrite

    Различие в команде по адресу 0x0085. Почему такая несправедливость и есть ли возможность ее поправить не прибегая к написанию на ассемблере (влом!!!)
     
  2. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    mha

    не нужно бояться использовать тег
    Код (Text):
    1.  
     
  3. Ustus

    Ustus New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2005
    Сообщения:
    834
    Адрес:
    Харьков
    mha

    С такой железкой не знаком, но если у нее int 16-бит, то попробуй
    Код (Text):
    1.  
    2. #define NUMBER_OF_SENSORS 2LU
    3. #define TIMEOUT_TO_SENSORS 30000LU
    4.  




    и еще - чтобы не было проблем - всегда в определении макроса бери параметры в скобки, т.е.
    Код (Text):
    1.  
    2. #define EnableMC13192Timer1(u32Timeout) \
    3. SPIDrvWrite(0x1B,(UINT16)(((u32Timeout) >>16) &0x000000FF) |0x000080FF); \
    4. SPIDrvWrite(0x1C,(UINT16)( (u32Timeout) &0x0000FFFF)); \
    5. SPIDrvWrite(0x1B,(UINT16)(((u32Timeout) >>16) &0x000000FF)); \
    6. SPIDrvWrite(0x1C,(UINT16)( (u32Timeout) &0x0000FFFF));
    7.  


    но в данном случае это несущественно.
     
  4. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    >> (u32Timeout >>16)

    Оператор >> имеет приоритет выше чем *. Поэтому нужно так:

    ((u32Timeout) >>16)



    ЗЫ: Опередили :)
     
  5. Ustus

    Ustus New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2005
    Сообщения:
    834
    Адрес:
    Харьков
    Quantum

    Нет, вот как раз наоборот, именно поэтому я и написал, что в ДАННОМ случае несущественно.

    По приоритетам:

    * / %

    + -

    << >>

    &

    ^

    |

    < <= > >=

    == !=

    &&

    ||
     
  6. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Ustus

    Верно, хотя в данном случае приоритеты одинаковые, т.к. >> 16 можно расценивать как деление на 2<sup>16</sup>.



    Возможно баг именно из-за деления, т.к. в первом вырианте очевидно, что операнд 16-битное беззнаковое число. Во втором случае это уже не очевидно и, скорее всего, сдвиг проводится арифметический, т.е. с сохранением знака. Поэтому результат -1, что после and даёт 0x00FF.



    mha

    Кроме скобок добавьте каст (UINT16) к u32Timeout.
     
  7. HitmaN85

    HitmaN85 New Member

    Публикаций:
    0
    Регистрация:
    6 окт 2005
    Сообщения:
    36
    u32Timeout везде в скобки возьми. Это главное правило макросов - параметры всегда в скобках.
     
  8. mha

    mha New Member

    Публикаций:
    0
    Регистрация:
    4 май 2006
    Сообщения:
    6
    Баг при использовании различных операций над константами при вызове макроса или процедуры компилятор также в некоторых случаях записывает неправильные значения в стек. Можно ли например в studio например влиять на повеение компилятора при вызове процедур кроме задания параметров _stdcall и тд. Както можно управлять компилятором С.
     
  9. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    mha



    А что ещё может понадобиться поменять в процедуре, кроме имени, генерации пролога/эпилога и соглашения о вызове? Студия позволяет всё это менять. О некоторых экзотических соглашениях она не знает или не желает знать, но их можно написать на асме и заинлайнить.





    cl.exe позволяет управлять практически всеми этапами компиляции через параметры командной строки. В сети где-то есть список даже недокументированных параметров, коих очень-очень много. Но начинать лучше с документированных -> msdn.
     
  10. Ustus

    Ustus New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2005
    Сообщения:
    834
    Адрес:
    Харьков
    mha



    Какой именно баг? Какие значения?

    Компилятор редко записывает неправильные значения :) Он может просто неправильно вас понять...



    Quantum



    Увы, компилятору вы это доказать не сможете :) Для него сдвиг - всегда сдвиг...
     
  11. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Ustus



    Понятно, что выдвинутая мною теория не выдерживает критики, но другого объяснения такому явному багу со знаком я не вижу. Имеем 2 явно беззнаковых операнда, операцию умножения и сдвиг. Никакого намёка на знаковость в этом выражении нет, но хвалёный CodeWarrior решил иначе. Забавно, что когда-то читал на их сайте статью, в которой они утверждали, что пользоваться бесплатными компиляторами, вроде GCC, небезопасно из-за возможных ошибок компиляции ;)
     
  12. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    mha

    Есть ли в CodeWarrior генерация файла с результатами работы препроцессора (типа /P в VC++) ?



    Попробуй указать явно беззнаковость всех констант

    например 0x000000FFU
     
  13. r90

    r90 New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2005
    Сообщения:
    898


    кстати о птичках... явно знаковых! В C, да и C++, дефолтовый тип для целого -- это int.
     
  14. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Нет такого понятия как дефолтовый тип. Тип всегда где-то должен быть указан.
     
  15. r90

    r90 New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2005
    Сообщения:
    898


    да, нету, но я имел в виду, что, напр., литерал `5' имеет в C тип int. и если я напишу:

    unsigned var = 5;

    то это подразумевает преобразование 5 типа int, к 5 типа unsigned.

    Чем не дефолтовый тип :)
     
  16. Ustus

    Ustus New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2005
    Сообщения:
    834
    Адрес:
    Харьков
    r90



    Если совсем точно по стандарту - то для целочисленного ДЕСЯТИЧНОГО литерала (если не используется явное указание суффиксом) тип является int, если значение представимо в нем. Иначе - unsigned int, если представимо в нем. Иначе - long, если т.с., иначе - unsigned long.

    Для шестнадцатиричного и восьмеричного литерала тип является unsigned int, если литерал представим в нем, иначе - unsigned long.

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

    Правда, нормальные компиляторы обычно выдают warning'и.



    Я поэтому и спрашивал про разрядность, т.к. если 16, -32768..+32767 то тип 60000 (0xEA60) - unsigned int. А вот тип 30000 - int, и 2 - тоже int. Поэтому тип 30000*2 тоже int и равен -5536 (0xEA60). То есть значение одно, а тип разный.

    В данном контексте это влияет на то, как будет выполняться сдвиг вправо - если это int, то старшие биты заполняются знаком, если unsigned - нулем.



    кстати, меня смущает строка:

    SPIDrvWrite(0x1B,(UINT16)((u32Timeout >>16) &0x000000FF) |0x000080FF);

    эквивалентно

    SPIDrvWrite(0x1B, 0x000080FF);

    ?