Главная » Bascom-8051, Basic, Железо » Ошибки и неприятности Bascom

0

1        Директивы $BAUD и $CRYSTAL активизируется только при использовании команд  PRINT, INPUT. Внимание!  Если  в  тексте  программы  не  применяются  операторы  PRINT,   INPUT,  то  инициализация  не выполняется – в таймер не загружается значение коэффициента деления, не инициализируются регистры SCON и PCON (см. соотв. раздел).

2  Внутри программной конструкции IF .. End If не допускается использование оператора Return:

Правильно:                                                                                  Неправильно:

If Tmp = 0 Then Goto Lcd_pe

End If

Lcd_pe:  Return

If Tmp = 0 Then Return

End If

При наличии записи Return происходит нарушение баланса стека и программа зависает.  Компилятор сообщений о такой ошибке не дает.

3      Функция Fusing работает правильно, если размер буфера, в который помещается  отформатированное число  (в  формате  с  плавающей  точкой),  несколько  больше,  чем  число  знаков  результата.  По  крайней  мере, требуется длина буфера равная сумме: максимальное количество чисел целой части + максимальное количество чисел дробной части + десятичная точка + знак полярности (минус для отрицательных чисел). В примерах Bascom не  зря   рекомендуется  применять  буфер   (символьную  переменную)  длиной  16  байт.  В  других   случаях суммирования двух символьных переменных нужно использовать буфер длиной не менее суммы максимальной длины  первой  переменной  +  длина  буфера,  содержащего  вторую  переменную.  Может  быть  это  и  не  так  – проверьте сами!

4      При использовании функции Fusing нужно так строить программу, чтобы не  приходилось выводить числа, которые не могут быть представлены в назначенном формате.  Лучше если они будут не больше и не меньше чем нужно. Проверяйте, что будете преобразовывать и, как получается во всем диапазоне преобразуемых чисел. Применяйте директиву $NONAN.

5        Другая  неприятность  функции  Fusing  заключается  в  том,  что  при   отрицательной  полярности преобразуемого числа знак минус входит в результат  форматирования, таким образом, одно и тоже значение положительной  и  отрицательной  полярности  выглядит  по  разному.  Существует  два  способа  борьбы  с  этим явлением: либо делать все числа на входе в преобразование положительными, а знак обрабатывать отдельно, или применять  различные  форматы  для  чисел  разной  полярности  (для  отрицательных  чисел  на  один  знак  слева больше).

6     Еще одна неприятность функции Fusing связана с тем, что лишние нули слева отбрасываются (вместо значения “003.45” при маске “###.##” мы получаем “3.45”). Бороться с этим можно только, контролируя длину результата и дописывая недостающие нули. В обновленной версии (1.0.0.19 и старше) этот недостаток исправлен введением дополнительных лидирующих нулей. Добавлена функция округления.

7       При  сборке  символьной  переменной  из  нескольких  частей  возможен  случай,  когда,  принимающая данные переменная, будет перекрыта по длине и следующая за ней переменная будет испорчена. Это происходит потому,  что  программа  копирует  не  содержимое  переменной  источника,  которое  не  столь  велико,  как  вы рассчитываете,  а  всю  переменную,  такой  длины,  как  она  была  объявлена.  Бороться  с  этим  можно  только увеличением  длины  переменной,  принимающей  символьные  данные.  Необходимую  степень  запаса  по  длине можно определить, наблюдая в отладчике за количеством испорченных ячеек. При этом, нужно иметь в виду, что при выводе длина символьного значения числовой переменной может меняться в значительных пределах (зависит от значения преобразуемого  числа). Также нужно учитывать, что длина внутреннего буфера Bascom, в котором формируется символьное значение числа, может достигать 16 при выводе значения переменной типа Single. Если за  принимающей  данные  переменной  располагается  стек,  то  неизбежен  фатальный  результат  этой  ошибки компилятора.

8     Длина строки исходного текста программы не должна превышать 255 символов, а реально получается даже  меньше.  Попытки  превзойти  ее  приводят  к  фатальному  сбою  компилятора.  Более  того,  это  не  дает возможность записать в одну строку некоторые необходимые вещи. Например, вывод текстового сообщения без символов ВК ПС:

Printbin &H42 ; &H41 ; &H42 ; &H43 ; &H44 ; &H45 ; &H46 …  ; &H4A ; &H4B

Или формирование длинной строковой переменной:

Out_buf = "S" + Str(rang) + "L" +Str(udac) + "T" … + Chr(13) + Chr(10)

9         Выполняя  операцию  вычисления  (очевидно,  какие-то  другие  тоже),  можно  назначить  в  качестве приемника данных любой регистр (любую переменную). Однако если  длина приемника не совпадает с длиной результата,  могут  возникнуть  неприятности.  Например,  операция,  дающая  двухбайтовый  результат,  будучи записана в переменную типа Long, модифицирует только два младший байта, а старшие разряды останутся без изменения. Ниже приведено два примера, дающие различные результаты. В первом примере имеется очевидная ошибка, которую компилятор не обнаруживает, и, наверно, не должен обнаруживать.

Dim Byt As Byte, Byt1 As Byte, Wrd As Word , Wrd1 As Word , Lng As Long Byt = 10 : Byt1 = 15 : Wrd = &H1234    ‘назначим числа

Wrd = Byt * Byt1     ‘произведение запишем в двухбайтное число

Printhex Wrd         ‘результат Wrd = 1296h – только в младших разрядах

Wrd = 16 : Wrd1 =  32 : Lng = &h12345678

Lng = Wrd * Wrd1     ‘произведение запишем в четырехбайтное число

Printhex Lng         ‘результат Lng = 12340200h – снова в младших разрядах

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

Byt = 10 : Byt1 = 15 : Wrd = &H1234    ‘назначим числа

Byt = Byt * Byt1     ‘произведение запишем в однобайтное число Wrd = Byt : Printhex Wrd  ‘результат Wrd = 0096h – правильный Wrd = 16 : Wrd1 =  32 : Lng = &h12345678

Wrd = Wrd * Wrd1     ‘произведение запишем в двухбайтное число

Printhex Lng         ‘результат Lng = 00000200h – снова правильно

Тем не менее, даже это, безусловно, вредное явление можно иногда использовать и с пользой.

10       Длина результата арифметических операций Bascom равна длине операндов (если они одного типа), что очень неудобно при необходимости выполнения операций  целочисленного умножения, например, 16 на 16 разрядов,  когда  желательно  получить  32-разрядный  результат.  Чтобы  получить  полноценный  результат  (32 разряда), приходится умножение выполнять в 32-разрядных регистрах (переменных). В итоге, время вычисления произведения увеличивается в десятки раз. Можно применять несколько облегченный вариант  – использовать, хотя бы один операнда, равный по длине требуемому результату, как в приведенном ниже примере.

Wrd = 50 : Lng =

2000

‘один из операндов возмем четырехбайтным

L ng = Wrd * Lng

‘произведение запишем в четырехбайтное число

Printhex Lng

‘результат Lng = 100000

11       Не все операторы Bascom могут работать с индексированными переменными,  определенными как элементы массива. При этом компилятор не выдает никаких сообщений. Собственно говоря, операторы работают, но только с первым элементом, адрес которого  совпадает с адресом массива. Чтобы обеспечить возможность работы  с  любым  элементом  массива  следует  применять  промежуточный  буфер,  куда  выгружать  данные  из массива перед обработкой или помещать после обработки и перед записью в массив. Например, оператор SWAP Ar(1), Ar(3) работает неправильно, поэтому вместо него следует записывать строку из трех операторов: Temp = Ar(1) : Ar(1) = Ar(3) : Ar(3) = Temp. Подобное решение, на самом деле, не увеличивает размер получаемого кода, т.к. внутри операторов, работающих с массивами, делают аналогичные пересылки.

12       В секции, определеной оператором DATA, константы (числа) и символьные значения адресов (метки) невозможно записать в виде символического имени. Нужно записывать  только  цифры. Главная неприятность этого заключается в том, что компилятор не дает сообщения об ошибке, а вместо ожидаемых значений записывает нули.

13         Имеется  ошибка  в  библиотеке  оператора  LOOKUP  при  считывании  четырехбайтного  числа  из таблицы. Как только индекс (смещение по таблице) превышает 63(3FH), начинается проявляться ошибка (неверно вычисляется   адрес   расположения   константы   из-за   того,   что   умножение   смещения   на   четыре   делается неправильно). В Последних версиях похоже устранено.

14       Символ  двоеточия  (“  :  ”)  недопустим  в  комментариях.  Если  такое  случается,  компилятор  дает сообщения о несуществующих ошибках и начинает искать метки с символами, расположенными в одной строке до знака двоеточия. А также символы ”<”, “>” и ключевые слова, обозначающие некоторые логические операции.

Справедливости ради нужно сказать, что в последних версиях (начиная с 1.20) ошибок  стало намного меньше, а фатальных незамечено вообще.

Источник: М.Л.Кулиш, СПРАВОЧНИК ПО ПРОГРАММИРОВАНИЮ BASCOM-8051, Краснодар 2001

По теме:

  • Комментарии