1 Отредактировано garnizon (21-01-2018 17:06)

Тема: Ошибки в ИКП-бейсике

Замечено что в ИКП-бейсике глючит функция VAL.

Если набрать программу (или запустить образ из вложения) :

5  PRINT "Нажмите две цифры"
10  GET A$: A =  VAL (A$)
20  GET B$: B =  VAL (B$)
30  PRINT A,B

Запускаем, нажимаем например 4,  потом 6

Получаем:

4.44444444e+16
6

т.е. первый раз функция VAL глючит, второй - нормально срабатывает.

Из-за этого например глючит игра ОХОТА НА ЛИС   - при нахождении последней лисы, сбрасывается в сообщение "Ошибочка вышла".

Как с этим бороться, реально ли поправить  это?

http://agatcomp.ru/Apps/Agatbasic.shtml

Post's attachments

Attachment icon 19_09_95b.dsk 840 kb, 302 downloads since 2018-01-06 

2 Отредактировано avivanov76 (29-08-2021 18:34)

Re: Ошибки в ИКП-бейсике

Собрался уже после этой темы http://forum.agatcomp.ru//viewtopic.php?id=148 долго и беспросветно копаться в Бейсике, но мне повезло удачно этот баг загуглить.
Вот тут есть дизассемблированный листинг Applesoft Бейсика с комментариями http://www.txbobsc.com/scsc/scdocumentor/

Нужный нам кусок - здесь: http://www.txbobsc.com/scsc/scdocumentor/E597.html
Это функция VAL, адрес $E707 (в ИКП Бейсике девятки - $E6C7).

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

Вот только есть одна проблема. Данные переменной A$ начинаются с адреса $BFFF и занимают 1 байт. Угадайте, куда запишется нулевой байт? Правильно, в $C000.

Дальше внутренние процедуры обработают введенный символ из $BFFF, а потом вместо нуля из $C000 прочтут последний введенный символ из регистра клавиатуры. И так пройдут по всем адресам $C000-$C00F. Получив в нашем случае строку из 17 повторов последнего символа.

Потом эти процедуры прочитают адрес $C010, а там - не цифра. Парсинг остановится.
Так что бага унаследована от Applesoft. В Apple она не проявляется - когда DOS загружен, рабочая область Бейсика заканчивается на $9600 и проблем не возникает. Но ИКП-шный Бейсик использует всю память от $1900 до $BFFF и бага проявляется.

* Интересно, что на семерке такого эффекта нет - там регистр клавиатуры чистится сам, и процедура парсинга получит свой нуль.

Вылечить такое поведение ИКП-шного Бейсика можно командой

HIMEM:-16385

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

3

Re: Ошибки в ИКП-бейсике

Аплодисменты в студию ! :)))

4

Re: Ошибки в ИКП-бейсике

Бурные и продолжительные аплодисменты звучат из Загорска!

5 Отредактировано vvhitevvizard (30-08-2021 14:53)

Re: Ошибки в ИКП-бейсике

Интересная находка!

avivanov76 пишет:

Вот тут есть дизассемблированный листинг Applesoft Бейсика с комментариями http://www.txbobsc.com/scsc/scdocumentor/

И спасибо за листинг Applesoft Бейсика с очень КАЧЕСТВЕННЫМИ комментариями, собранными из разных мест!!, что само по себе бесценно.

В нем автор выделил (<<<) несколько других багов и мест для улучшений, что может быть интересно и для изучения Агатовских Бейсиков:
I have flagged about a half dozen bugs in the listing, and several areas of very "improve-able" code. These are marked with "<<<" and ">>>" at each end of the comment lines.


До кучи, может кому будет полезно: "Системный монитор" Apple ][ с комментариями. В виде одного .asm файла.
http://www.easy68k.com/paulrsm/6502/MON.TXT
----
И еще о том, cколько всего версий Microsoft 6502 Бейсика (Apple, Commodore итд) и какие правки/оптимизации делались (включая исходник для компиляции всех этих версий):
https://www.pagetable.com/?p=46

6 Отредактировано Voldemar0 (28-03-2023 07:51)

Re: Ошибки в ИКП-бейсике

Сейчас прислали интересную багу бейсика (повторяется в Бейсика-60, ИКП-Бейсик-7 и Basic Master 95):

"4E" с любой последующей цифрой интерпретатор понимает как 40.
Без последующей цифры - как "4". Никаких сообщений о синтаксической ошибке.

]?4E                            
4      
       
]?4E6  
40     
       
]?4E4  
40     
       
]?4E0  
40

]?4E+0 
4

]?4E+1
40

]?4E+2 
400

]?4E+3 
4000

]?4E+4 
40000

]?4E-4 
4E-04

Попробовал в РАПИРе - там нормально всё: 4E+3 или 4E3 :

#BЫBOД:4E+3;                   
4000.0

7

Re: Ошибки в ИКП-бейсике

Смешная бага. Вернее, не бага, а фича.

Сначала я подумал, что тут что-то не то с преобразованием строки в число (процедура FIN в Бейсике Apple ][). Но код ее выглядит в ИКП-7 точно так же, как и в Apple.

Кроме того, я посмотрел содержимое буфера входной строки после выполнения команды ]?4E6.
В Apple оно такое:

200: BA 34 45 36 00 ; ?4E6.

А в ИКП-7 такое:

200: BA 34 01 02 00 ; ?4...

Что это значит, сразу я не понял и решил, что дело в процедуре PARSE.INPUT.LINE, которая подготавливает введенную строку к выполнению. Проблема в том, что эту процедуру в ИКП-7 не просто перенесли в другой банк ПсевдоПЗУ, но и переписали заново, с учетом всех дополнительных фич (ассемблера и т.п.). Поэтому сравнивать ее с Бейсиком Apple ][ бесполезно: отличий слишком много.

Тогда я задумался, а не принимает ли Бейсик эту запись за что-то другое?
Набрал

]?E6

Бейсик ответил мне:

]0

Ага! А что, если так?

]E6=10
]?E6

И Бейсик ответил:

]10

То есть, в данном случае E6 понимается как имя переменной. Ее начальное значение 0, поэтому команду ?4E6 Бейсик воспринимает как печать числа 4 и переменной E6.

8

Re: Ошибки в ИКП-бейсике

Че-то в припоминаю в старых книжках было такое: аргументы оператора print должны быть разделены либо запятой, которая будет заменена символом табуляции, либо точкой с запятой, которая ни в каком виде не будет отображаться. Точка с запятой в конце вывода запрещает вывод символа перевода строки.
Также и вариант оператора INPUT с подсказкой: строка-подсказка должна быть отделена от имени вводимой переменной (или от списка вводимых переменных) точкой с запятой.
Это было формальное описание в каком-то бейсике.

Но в агатовском я точно помню, что строковые константы никто никогда не отделял от имён переменных.
А вот одну переменную от другой вроде бы я отделял точкой с запятой, но вообще две переменных подряд редко бывает нужно вывести, разве что результаты расчётов удобно через запятую-табуляцию выводить.
А численные константы в print вообще, наверное, нигде никто не вставлял внутри программ...

Век живи, век учись...

9

Re: Ошибки в ИКП-бейсике

Ну вот. Накопал еще одно странное поведение Бейсика.
Есть оператор TAB, который используется внутри оператора PRINT.
Он должен ставить курсор в указанную горизонтальную позицию экрана. Типа, пишем TAB(10) и дальше вывод пойдет начиная с 10 позиции.

Вот программка:

10 PRINT TAB(4);"A";TAB(8);"B"
20 PRINT "1234567890"

Запускаем на Apple ][:

   A   B
1234567890

Вроде все сходится. A вывелось в четвертой позиции, B в восьмой.

Запускаем на Агате (Бейсик-60):

   AB
1234567890

Запускаем на Агате (ИКП-7):

      AB
1234567890

???

А если так:

10 PRINT TAB(5);"A";TAB(10);"B";TAB(15);"C"
20 PRINT "12345678901234567890"

Запускаем на Apple ][:

    A    B    C
12345678901234567890

Запускаем на Агате (Бейсик-60):

    AB  C
12345678901234567890

Запускаем на Агате (ИКП-7):

        AB        C
12345678901234567890

Магия! Что хотели этим сказать авторы агатовских Бейсиков - не понимаю.

10 Отредактировано Voldemar0 (28-11-2023 17:58)

Re: Ошибки в ИКП-бейсике

> Магия! Что хотели этим сказать авторы агатовских Бейсиков - не понимаю.

;) Мне кажется, они как раз с PDP реализацию TAB сделали.
Там TAB - это что-то связанное с табуляцией - т.е. с символом 011 или \t.
Он вызывает горизонтальное перемещение курсора до очередной позиции, кратной 8.
Это для рисования таблиц довольно удобная штука.

А для перехода на произвольную позицию у агатовского бейсика неплохо работает SPC и HTAB.
Ну как неплохо: HTAB не учитывает выбранный текстовый режим.
В каком-то режиме правильно работает, а в другом двоит или делит на 2 позицию... Не помню, но что-то там такое было.

11

Re: Ошибки в ИКП-бейсике

Voldemar0 пишет:

Ну как неплохо: HTAB не учитывает выбранный текстовый режим.

Проверил. В ИКП-7 HTAB во всех текстовых режимах работает нормально. В Бейсике 60 косячит: в Т32 все нормально, в Т64 шаг удвоенный.

Прогнал все примеры с TAB в режиме T64 (выполнил команду TEXT=47), и все заработало нормально в обоих Бейсиках. То есть, TAB косячит именно в режиме Т32.

Даже странно: или работу этого оператора вообще не проверяли, или проверяли только в режиме Т64. Хотя это более удобный вариант выводить что-то в табличной форме - все можно вывести одним оператором PRINT.
При использовании HTAB PRINT-ов нужно несколько.

12

Re: Ошибки в ИКП-бейсике

> Проверил. В ИКП-7 HTAB во всех текстовых режимах работает нормально. В Бейсике 60 косячит: в Т32 все нормально, в Т64 шаг удвоенный.

Мне кажется, это даже в доках на Бейсик-60 упомянуто. Если так, то это не ошибка, а фича Ж)

> Даже странно: или работу этого оператора вообще не проверяли, или проверяли только в режиме Т64. Хотя это более удобный вариант выводить что-то в табличной форме - все можно вывести одним оператором PRINT.

Может быть правили по бинарнику, переводя с Apple ][ на Агат и где-то не хватало места для нормальной реализации.

13

Re: Ошибки в ИКП-бейсике

Voldemar0 пишет:

Мне кажется, это даже в доках на Бейсик-60 упомянуто. Если так, то это не ошибка, а фича Ж)

Смотрел документацию на сайте и что-то ничего такого не нашел. Может, плохо искал. В документации 1985 года про это просто ничего нет.
В документации 1989 года http://agatcomp.ru/agat/Paper/DocsShtat … 1989.shtml после текста "HTAB X   - передвигает курсор на Х-ю позицию текущей экранной строки." добавили текст "В режиме 32*32   1<=X<=32, в режиме 64*32   1<=X<=64, в режиме APPLESOFT 1<=х<=40". Но опять же, ничего нет про двойной шаг.

14 Отредактировано avivanov76 (15-01-2024 00:09)

Re: Ошибки в ИКП-бейсике

Разобрался с оператором TAB.
Нужный кусок кода Бейсика Apple находится здесь https://www.txbobsc.com/scsc/scdocumentor/DACF.html
Процедура называется PR.TAB.OR.SPC (адрес $DB16).

Работает оператор TAB так: он берет аргумент и вычитает из него сначала единицу, а потом текущую позицию курсора. Если получился ноль или положительное число, то оно внутри TAB передается оператору SPC, который печатает нужное число пробелов. Если получилось отрицательное число, то TAB игнорируется и печать начинается с текущей позиции курсора.

Процедуры вывода на экран хранят горизонтальную позицию курсора в ячейке $24. Но в Агате это уже не совсем позиция курсора. В режиме Т32 это номер байта, а поскольку в этом режиме каждый символ занимает два байта (символ и его атрибут), то номер байта в два раза больше, чем позиция курсора.

Как с этим поступает Бейсик-60?
Да никак. Отличий между Apple и Бейсик-60 в коде процедуры нет (адрес $DB13).

Смотрим наш пример:

10 PRINT TAB(4);"A";TAB(8);"B"
20 PRINT "1234567890"

Поскольку первый PRINT начинается на новой строке, то значение ячейки $24 равно 0 и первый TAB работает как положено.
Однако после печати символа "A" позиция курсора равна 4, а вот значение ячейки $24 равно 8.
Второй TAB должен поставить курсор в 8 позицию. Чтобы проверить, не проехал ли он эту позицию, он берет аргумент (8) и вычитает из него единицу и значение из ячейки $24. А там тоже 8 :) Получается -1 и оператор TAB игнорируется. Символ "B" печатается сразу вслед за "A".

Похоже, багу просто не заметили.

С ИКП-7 все смешнее. Багу заметили, код исправили. Но... наполовину. Может задание на исправление было криво сформулировано, может проверять было лень, но получилась какая-то ерунда. Смотрим код:

DA98    CA        DEX           ; в X аргумент TAB, вычитаем 1
DA99    8A        TXA
DA9A    24 32     BIT    $32    ; проверяем режим (Т32/Т64)
DA9C    30 01     BMI    $DA9F
DA9E    0A        ASL           ; режим Т32, удваиваем аргумент
DA9F    38        SEC
DAA0    E5 24     SBC    $24    ; вычитаем позицию курсора, она же номер байта
DAA2    90 05     BCC    $DAA9
DAA4    AA        TAX           ; результат отдаем оператору SPC

Что сделали для исправления ошибки? Проверили видеорежим (старший бит ячейки $32 равен нулю в режиме Т32). Если включен Т64, все работает как и раньше. Если включен Т32, то аргумент TAB удваивается. Потом из него вычитается позиция курсора (которая в этом режиме равна номеру байта), и... все. Поделить результат пополам забыли.
В нашем примере аргумент первого TAB - это 4. Вычитаем 1, получаем 3. Удваиваем, получаем 6. Вычитаем номер байта (0), получаем 6. Печатаем 6 пробелов, а потом "A". Ну вот оно и вывелось в 7-й позиции. Зашибись!

15

Re: Ошибки в ИКП-бейсике

Решил проверить еще одну функцию, которая тоже завязана на ячейку $24 - функцию POS.
Она должна возвращать текущую горизонтальную позицию курсора.
Нужна такая возможность нечасто. Разве что, если делать на Бейсике что-то типа текстового редактора или оконного вывода.
Еще один пример использования я видел в руководстве по MSX Бейсику - там можно повесить вызов подпрограммы на таймер. На основе этого сделана программа "Часы": таймер срабатывает, текущая позиция курсора запоминается, в верхнем левом углу экрана печатается время, а потом курсор возвращается туда, где стоял.

В общем, эта ненужность и незаметность привели к тому, что ошибку в функции POS тоже никто не заметил :)

Вот тестовая программка:

10  DIM P(9)
20  FOR I = 0 TO 9
30 P(I) = POS(0)
40  PRINT "*";
50  NEXT
60  PRINT
70  FOR I = 0 TO 9: PRINT P(I): NEXT

Она печатает 10 звездочек и перед печатью каждой звездочки запоминает позицию курсора в массиве. А потом печатает позиции курсора.

Что получается в Бейсике Apple ][:

**********
0
1
2
3
4
5
6
7
8
9

Что получается в Бейсик-60 и ИКП-7:

**********
0
2
4
6
8
10
12
14
16
18

То есть, тут та же самая проблема - читается ячейка $24, а там не позиция курсора, а номер байта.

16

Re: Ошибки в ИКП-бейсике

Я могу сказать, для чего сам бы в те годы использовал бы что-то вроде POS.

Такой сюжет: есть прога со свободным перемещением курсора (используя стрелки, чистку экрана, enter, ввод каких нибудь символов). Прога просто читает код через GET A$, а потом вывод через PRINT A$;.

А теперь, в какие-то моменты, я хочу знать координату курсора, например, когда нажимается кнопка какой-нибудь буквы. Допустим, что я его запоминаю в массиве: символ и положение курсора (не хватает ещё какой нибудь фунции VPOS или LINE). И потом этот массив сохраняю в файл. При небольшом количестве введённых символов получается что-то вроде компактной программы рисования текствого экрана (без необходимости сохранять всё видеоозу).

В чём преимущество такого подхода: мне не нужно знать всю логику процедур движения курсора. Просто скидываю символ от ввода на вывод и фильтрую нажатия буквенных клавиш (if A$ >= "A" and A$ <= "Z").

Для начинающего программиста вполне полезная штука.

17

Re: Ошибки в ИКП-бейсике

avivanov76 пишет:

Что получается в Бейсик-60 и ИКП-7:

**********
0
2
4
6
8
10
12
14
16
18

А такое в обоих текстовых режимах, и 32 и 64?

18

Re: Ошибки в ИКП-бейсике

Нет, проблема только с Т32. Там номера байтов с позицией курсора не совпадают.

19

Re: Ошибки в ИКП-бейсике

avivanov76 пишет:

Нет, проблема только с Т32. Там номера байтов с позицией курсора не совпадают.

Вот я и подумал об этом. Т.е. если включить Т64, то оператор будет работать корректно. Хоть это хорошо :)