Пишу, по большей части, про историю, свою жизнь и немного про программирование.

99 бутылок: Ассемблер 6502 для Apple I

66. Ассемблер 6502 для «Эпл I». 6502 — восьмибитный микропроцессор, выпускавшийся в 1975 году компанией «МОС Текноложи».

У процессора всего 56 команд (не считая недокументированные), доступны три регистра — A, X и Y. Очень необычно устроена адресация — первые 256 байт памяти доступны через восьмибитную адресацию, всё остальное пространство — через шестнадцатибитную.

Мнемоники трёхбуквенные, в основном — смысловые сокращения или акронимы, запоминаются легко. Например, LDY — LoaD Y, ASL — Arithmetic Shift Left, JSR — Jump to SubRoutine и так далее.

Процессор использовался в первом персональном компьютере «Эпл», для него я и написал «песню про пиво», использовав для печати на экран куцее встроенное АПИ.

Очень помогло, что в наборе команд есть десятичный режим — в этом режиме после прибавления единицы к «09h» получается «10h», а не «0Ah» (надо только помнить, что в этом режиме работают всего две команды — ADC и SBC). «Бутылки» в этом режиме считать значительно легче.

.ORG    00280h
            .CPU    6502

ECHO        =       $FFEF
PRBYTE      =       $FFDC
PRHEX       =       $FFE5
MONITOR     =       $FF1F

            SED
            LDA     #$99
LOOP_:
            PHA
            JSR     BOTTLES
            JSR     B_OF_T_WALL
            LDX     #(ENDPASSSTR - STRS - 2) ; ", "
            LDY     #2
            JSR     PRINT
            PLA
            PHA
            JSR     BOTTLES
            JSR     OF_BEER
            JSR     DOT_CR
            JSR     TAKE_ONE_DOWN
            PLA

            SEC
            SBC     #1

            PHA
            JSR     BOTTLES
            JSR     B_OF_T_WALL

            JSR     DOT_CR

            PLA

            CMP     #0
            BNE     LOOP_

            JSR     NO_MORE

            JMP     MONITOR

PRINTNUMBER:         ; in A (number), use A
            CMP     #$F
            BCS     $+5
            JMP     PRHEX
            JMP     PRBYTE

PRINT_PSTR:          ; in X (offset), use A, Y
            LDY     (STRS),X
            INX
PRINT:               ; in X (offset), Y (len), use A
            LDA     (STRS),X
            JSR     ECHO
            INX
            DEY
            BNE     PRINT
            RTS

BOTTLES:             ; in A (quantity), use X, Y
            CMP     #0
            BEQ     NO_
            PHA
            JSR     PRINTNUMBER
            LDX     #3 ; skips len+"NO"
            LDY     #8 ; length of " BOTTLES"
            PLA
            CMP     #1
            BNE     NO_ONE_
            DEY      ; 7 - length of " BOTTLE"
NO_ONE_:
            JMP     PRINT

NO_:
            LDX     #0
            JMP     PRINT_PSTR

B_OF_T_WALL:         ; use X, Y, A
            LDX     #(BEERONTHEWALLSTR - STRS)
            JMP     PRINT_PSTR

OF_BEER:             ; use X, Y, A
            LDX     #(BEERONTHEWALLSTR - STRS + 1) ; skips len
            LDY     #8 ; length of " OF BEER"
            JMP     PRINT

DOT_CR:              ; use X, Y, A
            LDX     #(END - STRS - 2) ; "." + CR
            LDY     #2
            JMP     PRINT

TAKE_ONE_DOWN:       ; use X, Y, A
            LDX     #(PASSSTR - STRS)
            JMP     PRINT_PSTR

NO_MORE:             ; use X, Y, A
            LDX     #(ENDSTR - STRS)
            JMP     PRINT_PSTR

STRS:
            .PSTR   "NO BOTTLES"
BEERONTHEWALLSTR:
            .PSTR   " OF BEER ON THE WALL"
PASSSTR:
            .PSTR   "TAKE ONE DOWN AND PASS IT AROUND, "
ENDPASSSTR:

ENDSTR:
            DB      128,"NO MORE BOTTLES OF BEER ON THE WALL, NO MORE BOTTLES OF BEER.",$8D
            DB      "GO TO THE STORE AND BUY SOME MORE, 99 BOTTLES OF BEER ON THE WALL.",$8D
END:

Для отладки, написания программы и перевода в машинные коды использовался довольно удобный «онлайн-ассемблер Асм80», для исполнения программы — «ОупенЭмулятор».

Сначала программу я вводил в эмулятор вручную, но потом обленился и написал программу для ввода шестнадцатеричного дампа внутрь эмулятора. Выложил на «Гитхаб», если кому-нибудь интересно.

Надеюсь как-нибудь повторно схожу в музей «Эпл» в Москве и введу эту программу в настоящий компьютер.

2 комментария
Александр Ермаков 2020

Евгений заходите в группу vk.com/club190222366

Евгений Степанищев 2020

Спасибо, загляну на огонёк)

Евгений Степанищев 2020

Комментарии для тех, кто захочет запустить программу:

1) программа для автоматического ввода в эмулятор запускается только под третим и выше Пайтоном, под вторым будет ошибка синтаксиса
2) вывод программы автоматического ввода надо направить в интерпретатор ЭплСкрипт: python3 transfer2openemulator.py | osascript
3) если возникает ошибка 1002 («execution error: System Events got an error: osascript is not allowed to send keystrokes» или «execution error: Получена ошибка от System Events: Отправка нажатий клавиш для osascript не разрешена»), погуглите «osascript 1002 permission issue», в интернете есть рецепт.