Разобрался с оператором 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-й позиции. Зашибись!