Agon Light и другие версии платформы Agon основаны на процессоре Zilog eZ80. eZ80 имеет 24-битное адресное пространство и поддерживает 16 мегабайт памяти по сравнению с 64 килобайтами оригинального Z80. eZ80 имеет два режима работы: стандартный режим Z80, который имеет 16-битные регистры, что позволяет легко адресовать 64 КБ памяти, но требует использования «банковских операций» для доступа к более чем 64 КБ памяти; и режим работы ADL (длинные адресные данные), который расширяет регистры до 24 бит, делая легко доступным все адресное пространство.
Когда мы рассматриваем языки программирования высокого уровня, для Z80 доступно несколько языков, но они ограничены 64 КБ памяти или имеют неудобные методы переключения банков для доступа к большему объему памяти.
Что касается языков программирования C, то существует несколько C-компиляторов Z80. На сегодняшний день сообщество Agon сосредоточилось на двух вопросах:
Среда разработки Zilog ZDS II , которая может создавать код ADL eZ80. Это был исходный набор инструментов, используемый разработчиками Agon, но он имеет закрытый исходный код, работает только в Windows и поддерживает только стандарт данных C89.
SDCC (C-компилятор для малых устройств) , популярный выбор для 8-битных компьютеров, и его адаптация для Agon была в центре внимания многих людей, занимающихся компьютером Agon. Это хороший компилятор для Z80, но он поддерживает только Z80, а не режим ADL.
В качестве альтернативы можно использовать набор инструментов CEdev C/C++ — это компилятор с открытым исходным кодом, который может создавать код ADL. Он ориентирован на калькулятор TI-84 Plus CE (на базе процессора eZ80) и имеет достаточно большое сообщество. CEdev основан на версиях eZ80 компилятора LLVM и ассемблера fasmg. Он создает код ADL с 24-битными указателями, 24-битными целыми числами, 32-битными длинными, 16-битными короткими значениями и 32-битными числами с плавающей запятой. Существует также довольно обширная библиотека для программ на C и C++ (хотя она пока не совместима с ISO...).
AgDev является результатом попытки изменить CEdev для соответствия набору функций и аппаратному обеспечению платформы Agon. В результате получается более мощный набор инструментов с поддержкой C++ по сравнению с другими вариантами Agon.
Загрузите сборку релиза или сборку из исходного кода самостоятельно. Поместите сборку в выбранную вами директорию.
После этого убедитесь, что папка /bin
находится в PATH
; если вы используете Windows, следуйте этому руководству или вместо этого можете запустить cedev.bat и выполнять команды оттуда. В Linux запустите export PATH=/<insert path here>/bin:$PATH
в окне терминала.
Здесь используется тот же подход, что и в оригинальной цепочке инструментов CE (см. нижнюю часть страницы начала работы с CEdev). Процесс сборки был изменен, чтобы остановить создание файла .bin
. Это исполняемый файл Agon Light.
Рекомендую использовать:
очистить сделать V=1
Команда make clean
может использоваться для удаления результатов предыдущих компиляций и, таким образом, принудительно выполнить перекомпиляцию.
Процесс сборки проходит следующие этапы:
Компиляция исходных файлов .c в биткод LLVM (.bc) с использованием ez80-clang
Связывание биткода LLVM с помощью ez80-link
. Это включает в себя оптимизацию времени соединения.
Генерация ассемблерного кода eZ80 (.src) для исходных программ с помощью ez80-clang
Сборка и связывание сгенерированного ассемблерного кода (начиная с шага 3) с библиотеками и средой выполнения компилятора с помощью fasmg
— это включает в себя создание исполняемого файла, ориентированного на определенную область памяти. Это основная часть процесса сборки, которую необходимо корректировать.
См. примечания к применению Zilog «Вызов C из asm.pdf».
Вызываемые функции должны сохранять только регистр IX и стек.
Аргументы передаются от последнего к первому, что соответствует прототипу C. В eZ80 в стек всегда помещаются 3 байта, независимо от фактического размера. Однако функция сборки должна быть осторожной и использовать только действительные передаваемые байты. Например, если используется короткий тип, верхний байт значения, помещаемого в стек, будет содержать произвольные данные. В этой таблице перечислены местоположения относительно sp внутри вызываемой функции. Обратите внимание, что sp + [0,2]
содержит адрес возврата.
Тип C/С++ | Размер | Расположение стека |
---|---|---|
голец | 1 байт | сп + [3] |
короткий | 2 байта | сп + [3,4] |
интервал | 3 байта | сп + [3,5] |
длинный | 4 байта | сп + [3,6] |
долго долго | 8 байт | сп + [3,10] |
плавать | 4 байта | сп + [3,6] |
двойной | 4 байта | сп + [3,6] |
указатель | 3 байта | сп + [3,5] |
Обратите внимание, что eZ80 имеет прямой порядок байтов, т. е. первым сохраняется младший байт.
В этой таблице перечислены регистры, которые используются для возвращаемых значений функции. Знак типа не влияет на используемые регистры, но может влиять на возвращаемое значение. LSB расположен в регистре в крайнем правом углу выражения, например E:UHL
указывает, что в регистре L
хранится LSB.
Тип C/С++ | Реестр возврата |
---|---|
голец | А |
короткий | ХЛ |
интервал | УХЛ |
длинный | Э: УХЛ |
долго долго | БК: УДЭ: УХЛ |
плавать | Э: УХЛ |
двойной | Э: УХЛ |
указатель | УХЛ |
Не соответствует требованиям ISO!
Состоит из следующего:
Файл ввода-вывода:
fopen()
, freopen(),
fclose()
fputc()
, fputs()
fgetc()
, ungetc()
, fgets()
feof()
, ferror()
, fflush()
fread()
, fwrite()
fseek()
, rewind()
, ftell()
clearerr()
remove()
Стандартный ввод-вывод/стандартный вывод:
putchar()
, puts()
getchar()
, gets_s()
Форматированный вывод
printf()
(и vprintf()
)
sprintf()
(и vsprintf()
)
snprintf()
(и vsnprintf()
)
Форматированный ввод
scanf()
sscanf()
Здесь есть еще кое-что, например stdint
и тому подобное, но в основном оно должно соответствовать ожиданиям обычной стандартной библиотеки. По большей части.
stdio
перенаправление Можно перенаправить вывод, используя freopen()
на stdout
или stderr
:
putchar()
— выводит в outchar()
, если вывод не перенаправлен, в этом случае выводится в fputc()
puts()
— вызывает putchar()
printf()
(и vprintf()
) — вызывает npf_putc_std()
, который вызывает putchar()
в nanoprintf.c
fputc()
— вызывает mos_fputc()
если он не вызывается на stdout
, когда вызывает outchar()
— избегает вызова putchar()
чтобы исключить риск зацикливания вызова функции
Можно перенаправить ввод, используя freopen()
на stdin
:
getchar()
— вызывает inchar()
для получения символа и outchar()
для повторного отображения символа (даже если вывод был перенаправлен). Если вывод не был перенаправлен, вызывает функцию fgetc()
и не отображает символ.
gets_s()
— вызывает getchar()
если ввод не был перенаправлен (строка завершается CR). Вызовы fgets()
ввода были перенаправлены (строки завершаются парой CR/LF).
scanf()
— вызывает getchar()
в uscan.c
(не требует обновления)
fgetc()
— вызывает mos_fgetc()
если он не вызывается на стандартный ввод, когда вызывается inchar()
и эхо с outchar()
— избегает вызова getchar()
, чтобы исключить риск зацикливания вызова функции
Требуется FILE *
, который представляет собой указатель на дескриптор файла, возвращаемый fopen
и передаваемый процедурам файлового ввода-вывода, чтобы указать файл, над которым должно быть выполнено действие.
Другие связанные файлы:
stdio.h
— обычные файлы заголовков, которые определяют различные функции и определение типа для FILE
files.c
— создает экземпляр хранилища для дескрипторов файлов, включая: stdout, stderr, stdin.
Определены следующие стандартные дескрипторы файлов:
stdout
— вывод по умолчанию
stderr
— вывод по умолчанию для сообщения об ошибке
stdin
— ввод по умолчанию
MOS не реализует перенаправление ввода/вывода, поэтому по умолчанию все они используют консоль.
Для обработки командной строки доступны два варианта.
Это автоматически включается, если основная функция определена как
int main( int argc, char* argv[])
разбивает командную строку, используя пробел в качестве разделителя. Параметры командной строки доступны в массиве argv[]
как обычно.
Это необязательно включается, если make-файл приложения включает:
LDHAS_ARG_PROCESSING = 1
Это поддерживает
Цитирование с двойными кавычками
Перенаправление ввода/вывода
>out_file.txt
— перенаправляет стандартный вывод на out_file.txt
, создавая новый файл.
>>out_file.txt
— перенаправляет стандартный вывод в out_file.txt
, добавляя его в конец файла.
<in_file.txt
— перенаправляет стандартный ввод из in_file.txt
Текущую документацию по командам MOS см. в документации Agon Console8.
MOS (операционная система компьютера) обеспечивает интерфейс для файловой системы Agon и некоторых периферийных устройств, таких как мышь. Он хранит информацию о системных переменных в большой структуре SYSVAR
, доступ к которой возможен на стороне Z80. Обычно ваш код C объявляет указатель на эту структуру, инициализируемую следующим образом:
статическая изменчивая SYSVAR* sv; св = vdp_vdu_init();
Для получения дополнительной информации см. <mos_api.h>
.
Текущую документацию по командам VDU см. в документации Agon Console8.
VDP (процессор отображения видео) принимает текстовый поток от MOS, действуя как текстовый/графический терминал. Текстовый поток может содержать:
Обычный текст
Escape-последовательности/команды для управления дисплеем и отправки графических/звуковых/т. д. команд.
Когда результаты возвращаются MOS в результате отправки команды, они сохраняются в SYSVAR
и не возвращаются непосредственно в ответ на команду. Ответ асинхронный — для проверки возврата результата:
Установите vdp_pflags
в SYSVAR
на ноль.
Выдайте команду VDU
Подождите, пока будет установлен соответствующий бит в vdp_pflags
— битовые маски см. в <mos_api.h>
Команды могут отправляться:
putch()
— один символ (это не часть стандартной библиотеки C)
mos_puts()
— многосимвольная строка
Оба они выводят непосредственно в MOS/VDP — обратите внимание, что они не являются частью библиотеки STDIO и не подлежат трансляции или перенаправлению CR/LF.
В AgDev предусмотрены удобные функции для многих команд VDU. Например, чтобы изменить РЕЖИМ экрана на 3, C вызывает vdp_mode(3);
отправит на выход 22,3
в виде отдельных байтов, что эквивалентно putch(22); putch(3);
Список этих функций см. в <vdp_vdu.h>
. Дополнительные функции, связанные с обработкой клавиатуры, находятся в <vdp_key.h>
.