Коды экранов от ASCII до C64 в DASM Ассемблере
Я изучаю ассемблер для 6502 micro через эмулятор C64. В данный момент пытаюсь вывести строки на экран. Вот мой код:
processor 6502
org $1000
ldx #$00 ;using x register as column counter
print:
lda message,x;load a with x bit from message
sta $0400,x ;store this bit in row 0 col 0 address
inx ;x++
cpx #$05 ;is x >= 5?
bne print ;if not x >= 5, loop again
rts ;return from program
message dc "HELLO"
hexmsg dc $08,$05,$0c,$0c,$0f
Поскольку мой редактор (notepad++ на win 10) использует ascii-подобные char-коды, "HELLO"
в message
это биты 48 45 4C 4C 4F. Это дает следующий вывод в верхнем левом углу экрана:
Я думаю, это правильно, если посмотреть на таблицу кодов экранов коммодора здесь.
Если я изменю строку 6 на lda hexmsg,x
тогда я получаю именно то, что мне нужно, слово HELLO
,
Я еще не очень знаком с ассемблером DASM и не могу найти полную документацию по нему (если он существует). Большинство учебных пособий, которые я нашел, только что вы объявили message .byte "HELLO"
или что-то подобное, и это просто работает, потому что ассемблер, который они используют, автоматически преобразует ascii-подобную текстовую строку в строку коммодора, но DASM, похоже, этого не делает.
Кто-нибудь знает, как я могу заставить DASM сделать это, или порекомендовать другой способ просто вводить строки в ассемблер, а не вводить вручную строки в виде набора шестнадцатеричных данных?
3 ответа
Вот исправленная версия DASM aseembler.
http://iancoog.altervista.org/C/dasm2.20.07-iAN_Rev_N.rar
Ты можешь использовать SCRU
а также SCRL
директивы для преобразования ASCII-> преобразование экранного кода.
label SCRU "string"
label SCRL "string"
SCRU
для создания заглавного текста, даже если он введен в нижнем регистре. SCRL
держит корпус.
Ага, кодировка ASCII против кодов экрана Commodore. Мы все были там. У вас есть несколько вариантов:
Не пишите напрямую в экранную память, а используйте вместо этого подпрограмму Kernal CHROUT (возможно, через процедуру вывода строк более высокого уровня). Тогда все, о чем вам нужно беспокоиться, это различия между ASCII и PETSCII, но это история для другого времени сна. Кроме того, это хорошо для текста, но отстой для игр, поскольку Kernal медленнее, чем прямые записи.
Напишите небольшую подпрограмму преобразования, которая запускается при запуске вашей программы, пожирает вашу таблицу строк и выплевывает преобразованные эквиваленты экранного кода. Быстро и эффективно, при условии, что все строки объединены, и вы не пишете приложение на основе ПЗУ (которое не сможет выполнить преобразование на месте).
Напишите препроцессор DASM, который запускается перед DASM в вашем скрипте сборки и в основном выполняет то же преобразование, что и #2 выше, но в исходный код до того, как ассемблер его увидит. Это может быть немного грубовато, и вы должны быть уверены, что сделали резервную копию исходного источника, прежде чем копировать его.
Получите исходный код DASM и исправьте его, чтобы вызвать пользовательский выход для нового типа данных (для экранных кодов), который выполняет те же функции, что и №2, но на лету во время сборки. Очень коряво.
Используйте строчные буквы в своих строках, которые будут преобразованы в эквиваленты кода экрана в верхнем регистре во время сборки. Возможно, вы упустили из виду тот факт, что вы видите смещенное представление символов в строке, которое в режиме отображения по умолчанию представляет собой графические символы.
Исходя из опыта всех 5 вариантов, я остановился на #2.
Также: переключитесь на KickAssembler, который
- новее и активно поддерживается
- предлагает более мощные функции
- очень хорошо интегрируется с VICE для отладки
Прошло некоторое время с тех пор, как я запрограммировал 6510. (Если вы не нажали для сохранения каждого отдельного байта памяти C64...) Также рассмотрите возможность обнуления вашей строки (строк) с помощью, скажем, байта 0, а не окончания длины, достигнутой в регистре X. Делает это немного более удобным, чем определение длины строки:D
processor 6502
org $1000
printstring:
ldx #$00
printstrlp:
lda message,x
cmp #0
beq quitstr
cmp #32 ;' ' character
beq noconv
cmp #33 ;! character
beq noconv
cmp #42 ;* character
beq noconv
cmp #48 ;numbers 0-9
bcs numconv
conv:
sec
sbc #$40
noconv:
sta $0400,x
inx
bne printstrlp
quitstr:
rts
numconv:
cmp #58
bcc noconv
jmp conv
message dc "** HELLO C64 WORLD! **",0
Если это может помочь, вот небольшой скрипт на Python, чтобы сделать это. Просто позвони с
python3 str_conv.py code.asm message
import argparse
import os
mapping = [
'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '~', ']', '|', '\\', ' ', '!', '"', '#', '$', '%', '&',
'\'', '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
':', ';', '<', '=', '>', '?'
]
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Convert ASCII to C64 screen codes')
parser.add_argument('file', help='assembly source code')
parser.add_argument('label', help='label used in DASM')
args = parser.parse_args()
filepath = os.path.join(os.getcwd(), args.file)
backup = os.path.join(os.getcwd(), args.file) + ".bck"
os.rename(filepath, backup)
label = args.label
new_code = []
found = False
for line_nb, line in enumerate(open(backup)):
if line.find("\\b{}\\b".format(label)) and '"' in line:
text = line[line.find('"')+1:line.rfind('"')]
new_line = "{}:\t.byte ".format(label)
for i, char in enumerate(text):
new_line += "{}{}".format(mapping.index(char), ", " if i != len(text)-1 else "\n")
print(line_nb, new_line)
new_code.append("; {}".format(line))
new_code.append(new_line)
found = True
else:
new_code.append(line)
if not found:
print("Label {} not found!".format(label))
else:
with open(filepath, "w") as new_file:
for line in new_code:
new_file.write(line)
print("Done!")