Sandro>> Вот пусть она мне корректную процедуру подсчёта единичных бит на ассемблере PDP-11 напишет. В прошлый раз этот исскуственный идиот облажался.
Татарин> Не понял... когда был прошлый раз?
Татарин> Вроде, корректно. Что тут неверно?
То, что сеть не знает ассемблера PDP-11.
Ошибки:
> mov #16, r2 ; устанавливаем счетчик битов
Система счисления по умолчанию — восьмеричная. #20 должно быть. А вообще действительно надо выходить по нулю в сдвиговом регистре.
Предыдущая версия кода от ChatGPT пыталась это делать, но неправильно.
> mov r0, r3 ; сохраняем слово в регистре r3
Половину скопипастил, половину нет. Эта манипуляция нужна для того, что принято возвращать результат в R0. Регистр освободил, но возвращает результат в R1. Нарушение де-факто стандартов и лишняя команда.
> ash #1, r3 ; сдвигаем слово влево на 1 бит
Команду ASL отменили? Ничего, что она есть на всех моделях, а ASH — только на машинах с полной EIS?
> br z, done ; если слово стало равно 0, переходим к завершению
Такой команды (br z,) не существует. Есть beq, но даже с ней код проимеет последнюю единицу.
> beq loop ; если старший бит равен 0, переходим к следующему биту
(правка) Вот блин, просмотрел, думал по комментарию хоть это поправили. Полночь уже тут у меня.
beq — это переход, если весь результат операции равен 0. А не старший бит. И даже проверка на старший бит неверна.
Просто сплошняком бред, это не может работать в принципе.
> inc r1 ; если старший бит равен 1, увеличиваем счетчик
Просто тупизм. ADC R1
> br loop ; переходим к следующему биту
А счётчик битов зачем был? Зачем константу в R2 запихивать нужно было? BR — это безусловный переход!
> rts ; завершаем процедуру, результат в регистре r1
Такой нотации ассемблера нет. Есть RTS R7. Есть её короткий синоним RET. Но не это.
Вывод — это даже не ошибочный код. Это склад ошибок компиляции и алгоритмических ошибок.
Правильно, например, так:
(правка — добавил комментарии)
popcnt: clr r1 ; обнулим счётчик единиц
loop: asl r0 ; выдвинем старший бит во флаг арифметического переноса; можно add r0, r0 -- совой об пень или наоборот ...
beq done ; если мы выдвинули все единичные биты -- готово
adc r1 ; добавим значение выдвинутого бита (0 либо 1) к счётчику
br loop ; продолжим с остальными битами, остались где-то единички
done: adc r1 ; выдвинули все единички, во флаге переноса либо 1 (последняя единичка), либо -- особый случай -- 0, если нам передали на вход нуль, добавляем, что там есть
mov r1, r0 ; перекладываем результат счёта в традиционное место (r0)
ret ; всё сделано, возвращаем управление вызвавшей нас подпрограмме
Кстати, по машкоду это ещё и на треть короче, чем бредни Искусственного Идиота.