Немного подшаманил дизассемблер. Следующая итерация бейсика 5.29: см. дальше.
Вид для печати
Немного подшаманил дизассемблер. Следующая итерация бейсика 5.29: см. дальше.
В 2.97 закралась ошибка в поиск строк, пофиксил. Очень специфическая, в готовых программах она не проявляется, поэтому не находил тестами. На нее можно наткнуться набирая программу в самом бейсике при хитром порядке номеров. Есть и хорошая новость - после исправления и доработки скорость не ухудшилась, а даже микроскопически улучшились (обновлять результаты тестов не стал, принципиальной разницы нет).
Больше тестов хороших и разных. Решето Эратосфена.
Скрытый текст
Код:10 DIM BS(500)
20 N=500
30 FOR I=2 TO N
40 IF BS(I)=0 THEN PRINT I;
50 J=1
60 IF I*J<=N THEN BS(I*J)=1:J=J+1:GOTO 60
70 NEXT
80 STOP
[свернуть]
Пробелы между операторами для совместимости с 5.29. 4.51 и 5.29 тестировал в Т-34.
4.51 (одинарн) - 49.96 секунды
4.51 (целые) - 41 секунда
5.29 (одинарн) - 46.58 секунды
5.29 (целые) - 36.58 секунды
2.5 - 46.55 секунды
2.891 - 39.38 секунды
2.995 - 20.2 секунды
2.996 - 19.47 секунды
Вклад вывода чисел на экран можно оценить сравнив с результатами без PRINT I (4.51 не позволил оставить просто THEN, поэтому тут его результатов нет)
5.29 (одинарн) - 45.24 секунды
5.29 (целые) - 35.7 секунды
2.5 - 44.61 секунды
2.97fix - 29.86 секунды
2.98 - 18.71 секунды
Полез смотреть целочисленную арифметику в 5.29 и понял, что с целыми придется частично перетестировать. В продвинутых микрософтовских бейсиках есть отдельное целочисленное деление \. Т.е. когда есть деление для перехода на полноцелочисленность не хватает DEFINT, надо менять / на \. И я ведь когда-то читал про это, но не придал особого значения, а разница весьма заметная. Деление используется в RFBM3-7 (в решете деления нет). RFBM3 выдает переполнение с \, там остается /. Результаты RFBM4-7 с \ добавил в таблицу. Но 2.97 не сдается даже когда в 4.51/5.29 используется \, в 2 тестах из 4 он впереди. Целочисленную арифметику в 5.29 по скорости особо не оптимизировали и в 4.51 явно не лучше, там большие резервы.
Подчистил "фантомные" метки в командах LXI (т.е. где должна быть константа). Наверное, больше уже ничего делать не буду.
Финальный дизасм бейсика 5.29: Вложение 78970
Арифметика с одинарной точностью в 5.29 оказалась несколько интереснее, чем ожидал.
Отличия от альтаирского 3.2 (и векторовского 2.5):
1. В цикл умножения добавили sticky bit, вероятно под влиянием IEEE, это немного замедляет умножение по сравнению с 3.2 и 2.5.
2.1. В деление добавили проверки при начальном увеличении экспоненты. Хорошая вещь, 3.2 и 2.5 могут пропустить переполнение при делении.
2.2. В окончании деления громоздко и коряво формируют троицу: guard bit, round bit, sticky bit, но дальше переходят на округление, где, как и в ранних версиях, учитывают только guard bit. Это или забывчивость или даже не знаю, как назвать.
3. Добавили оптимизацию частных случаев (когда есть нули) в сдвигах мантиссы вправо и влево. Тут я оказывается попал в тренд, в своих модификациях оптимизировал сдвиги вправо (и на мой субъективный взгляд сделал это лучше). Сдвиги влево пробовал менять, но в итоге в релиз не включил (не хватало места). Наверно зря, особенно если сравнить с тем, как в 5.29, надо было изыскать резервы. Кстати, в отличие от умножения и деления, в сдвиги вправо sticky bit не добавили.
4. У меня сложилось впечатление, что модификаторы бейсика совсем не напрягались. Для примера вместо того, чтобы убрать в нормализации лишнюю команду, которая ошибочно там оставалась с 3.2 (просто занимала 1 байт места и время на выполнение) они "исправили" ее на 3х байтовую, молодцы. Ну и они оставили некоторые старые неоптимальные решения, на мой взгляд бросающиеся в глаза, и добавили своих еще менее впечатляющих.
По пробелам чемпион 4.51, там можно пробелы и в именах переменных, как в 3.2 (и 2.5+) и во всяких GO*UB, как в 5.29. А в 5.29 ужесточили с именами переменных. Думаю это один из источников ускорения 5.29, пробовал так делать в своей модификации - становится немного быстрее.
Извращенцы:
L0FBE сравнивает строки, только вот L1305 пропускает одну букву. При таком раскладе должно было работать GO ATO, но вместо этого получается GOSUB (JZ L0FB8 явно переходит на пару байт раньше). Победить не смогли, поэтому просто добавили GO TO в таблицу операторов:Код:PUSH H
LXI D,L0FCC
CALL L0FBE
JNZ L0FD6
CALL L1305
LXI D,L0FD0
CALL L0FBE
MVI A,89h
JZ L0FB8
LXI D,L0FD3
CALL L0FBE
JNZ L0FD6
L0FB8:
MVI A,8Dh
POP B
JMP L1048
L0FBE:
LDAX D
ORA A
RZ
MOV C,A
CALL L1C5A
CMP C
RNZ
INX H
INX D
JMP L0FBE
L0FCC:
DB 'GO ',0
L0FD0:
DB 'TO',0
L0FD3:
DB 'UB',0
Микрософт :)Код:OPS_G:
DB 'OT','O'+80h
DB 89h
DB 'O T','O'+80h
DB 89h
DB 'OSU','B'+80h
DB 8Dh
DB 'E','T'+80h
DB 0C1h,0
Понятно, что хотели как лучше - помочь неопытной части англоязычных пользователей, которые могут написать go to или go sub с пробелом, но реализация позорная. У меня получилось нормализовать приведенный фрагмент тремя исправлениями, многовато для простой задачи.