Кросс-ассемблер для PDP11/8080 (Windows/Linux, open-source)

Использование и разработка софта (преимущественно на ПЦ)

Moderator: Shaos

Post Reply
alemorf
Senior
Posts: 132
Joined: 03 Jan 2017 15:58
Location: SPb
Contact:

Кросс-ассемблер для PDP11/8080 (Windows/Linux, open-source)

Post by alemorf »

Программа оказалась (относительно) востребованной, уже год просят доработать, поэтому я возрождаю разработку.

https://github.com/alemorf/pdp11asm

Изменения:
5-01-2017 Добавил директиву include.

Последняя информация по кросс-ассемблеру:

Команды программы

.INCLUDE "file"
Подключить файл

ORG N
.LINK N
Устанавливает адрес, куда будет выводится код после этой команды. По умолчанию используется адрес 0.

DB
.BYTE
Записать байты. Через запятую можно указывать числа, 'A' - код символа, "ABCD" - несколько кодов символов. Так же поддерживается конструкция N DUP(C) записывающая N раз байт C.

DW
.WORD
Записать слова.

.ASCII /text/
Записать текст.

.END
Игнорируется

.BLKB N
Вывести N байт 0.

.BLKW N
Вывести N слов 0.

name EQU value
name = value
Установить константу. Во всем файле name будет автоматически заменяться на value.

name:
Метка. Во всем файле name будет заменяться на адрес метки. Указывать : после метки не обязательно. Вместе с игнорированием пробелов и переносов строк, синтаксис ассемблера стал очень свободным. Хоть в одну строку пиши.

N:
Числовая метка. Область действия метки ограничивается символьными метками. Такая метка может быть использована только в командах условного перехода B? и SOB.

MAKE_BK0010_ROM "filename", start, end
Сформировать файл поддерживаемый эмулятором B2M. start, end - начальный и конечный адрес программы. Можно использовать метки.

MAKE_BINARY_FILE "filename", start, end
Выгрузить образ памяти в файл. start, end - начальный и конечный адрес. Можно использовать метки.

INSERT_FILE "filename", offset, size
Вставить двоичный файл. Можно вставить часть файла, задав размер и смещение в исходном файле.

ALIGN N
Выровнять адрес следующей команды на N-байт.

CONVERT1251TOKOI8R
Включить преобразование строк из кодировки 1251 в KOI8R.

CONVERT1251TOKOI8R OFF
Выключить преобразование строк из кодировки 1251 в KOI8R.

DECIMALNUMBERS
Далее все числа по умолчанию 10-ричные. В стандарте C.

DECIMALNUMBERS OFF
Далее все числа по умолчанию 8-ричные. В конце 10-чных чисел необходимо ставить точку.

INSERT_BITMAP1 "name", width, height
Вставить изображение преобразовав его в формат видеопамяти БК0010 2 цвета. Изображение должно быть в формате BMP 24 бита. width, height должны соответствовать размеру
изображения в файле.

INSERT_BITMAP2 "name", width, height
Вставить изображение преобразовав его в формат видеопамяти БК0010 4 цвета. Изображение должно быть в формате BMP 24 бита. width, height должны соответствовать размеру изображения в файле.

INSERT_BITMAP1T "name", width, height
Вставить изображение преобразовав его в NAND и OR маски 2 цвета. В качестве прозрачного цвета используется #FF00FF.

INSERT_BITMAP2T "name", width, height
Вставить изображение преобразовав его в NAND и OR маски 4 цвета. В качестве прозрачного цвета используется #FF00FF.

; text
// text
Комментарий

.
Адрес этой команды

Команды процессора без аргументов

HALT Останавливает ЦП
WAIT Останавливает ЦП до прерывания
BPT Вызов прерывания
IOT Вызов прерывания
EMT 0..255 Вызов прерывания
TRAP 0..255 Вызов прерывания
MARK 0..63 Вызов прерывания
RESET Перезагрузка процессора
RTI Выход из прерывания (Загружает PC, PS из стека)
RTT Выход из прерывания пошаговой отладки.
NOP Ничего не делает
CLC Сбрасывает флаг C
CLV Сбрасывает флаг V
CLZ Сбрасывает флаг Z
CLN Сбрасывает флаг N
СCC Сбрасывает все флаги
SEC Устанавливает флаг C
SEV Устанавливает флаг V
SEZ Устанавливает флаг Z
SEN Устанавливает флаг N
SCC Устанавливает все флаги
RET Синоним RTS PC

Команды процессора с одним аргументом

(B) описании значит, что существует две версии команды CLRB - обрабатывающей байты и CLR - обрабатывающей слова.

JMP r Переход по адресу
SWAB r Поменять старший и младший байты местами
CLR(B) r Записать 0
COM(B) r Инверсия (заменть все биты на противоположные)
INC(B) r Увеличить на единицу
DEC(B) r Уменьшить на единицу
NEG(B) r Изменить знак
ADC(B) r Увеличить на единицу, если C=1
SBC(B) r Уменьшить на единицу, если С=1
TST(B) r Сравнить с нулем
ROR(B) r Циклический сдвиг вправо через флаг C
ROL(B) r Циклический сдвиг влево через флаг C
ASR(B) r Cдвиг вправо, старший бит дублируется
ASL(B) r Cдвиг вправо, младший бит равен 0
SXT r Расширение знака. Если N=0 записывает 0, иначе -1
MTPS r Установка регистра флагов
MFPS r Чтение регистра флагов
CALL r Синоним JSR PC,

Аргументы команды

R0, R1, R2, R3, R4, R5, SP, PC Регистр. Все регистры 16 битные. 8 битные команды будут работать с младшими их половинами.
(REG) или @REG Значение по адресу
@(REG) Значение по адресу по адресу.
-(REG) Значение по адресу. Уменьшить регистр до выполнения команды на 1 для байта. И на 2 для слова.
@-(REG) Значение по адресу по адресу. Уменьшить регистр до выполнения команды.
(REG)+ Значение по адресу. Увеличить регистр после выполнения команды на 1 для байта. И на 2 для слова.
@(REG)+ Значение по адресу по адресу. Увеличить регистр после выполнения команды.
IMM(REG) Значение по адресу, который рассчитывается как сумма регистра и числа.
@IMM(REG) Значение по адресу по адресу, который рассчитывается как сумма регистра и числа.
#A Число или адрес переменной.
@#A Значение по адресу или переменная. Абсолютная адресация.
A Значение по адресу или переменная. Адрес относительно PC.
@A Значение по адресу по адресу. Первый адрес относительно PC.

Команды процессора с двумя аргументами

MOV(B) a, b Скопировать
CMP(B) a, b Сравнить A и B
BIS(B) a, b Логическое ИЛИ
BIС(B) a, b Логическое И-НЕ (B = B & ~A)
BIT(B) a, b Логическое И без сохранения результата
ADD a, b Сложение
SUB a, b Вычитание

Команды условного перехода

Могут переходить только в пределах -256..+254 байта, относительно адреса следующей команды. Числа указанные в аргументе команды интерпретируются как числовые метки.

BR imm Всегда
BNE imm Не равно (Z=0)
BEQ imm Равно (Z=1)
BGE imm Больше равно для знаковых типов (N^V=0)
BLT imm Меньше для знаковых типов (N^V=1)
BGT imm Больше для знаковых типов (Z|(N^V)=0)
BLE imm Меньше равно для знаковых типов (Z|(N^V)=1)
BPL imm Результат положительный (N=0)
BMI imm Результат отрицательный (N=1)
BHI imm Больше (C|Z=0)
BVC imm Нет знакового переполнения (V=0)
BVS imm Знаковое переполнение (V=1)
BHIS imm / BCC imm Больше или равно / нет переполнения (C=0)
BLO imm / BCS imm Меньше / переполнение (C=1)

Необычные команды процессора

JSR reg, a Вызвать подпрограмму (REG - только регистр, A - любой аргумент)
RTS reg Выход из подпрограммы (REG - только регистр)
XOR reg, a Исключающее ИЛИ (REG - только регистр, A - любой аргумент)
SOB reg, imm Цикл (REG - только регистр, IMM - адрес). Числа указанные в аргументе IMM команды интерпретируются как числовые метки.

Особенности

- Некоторая совместимость с транслятором MACRO11. Но макросов нет.

- Примитивная арифметика. Например текст 2+5-1 будет преобразован в число 6. Соответственно Label1 + 6 это адрес на 6 больше адреса метки Label1.

- Со скобками надо быть осторожнее, скобки вокруг аргумента так же обозначают режим адресации: (1+2) - это значение по адресу 3, (1+2)*1 - это значение 3.

- Числовые метки. Например "10:". Их область видимости ограничена символьными метками. И их можно использовать только с командами условного перехода: B? и SOB. Любое положительное число в аргументе этих команд интерпретируется как метка.

- При таком подходе любимая PDP-шниками команда "SOB R1, .-2" не работает, так как 2 интерпретируется как метка. Но благодаря исключению с отрицательными числами можно написать "SOB R1, .+-2". -2 в тут считается числом на уровне парсера. Похоже на костыль, но я не знаю как сделать красивее. (Знал, но проект давно остановлен и я опять забыл)

- По умолчанию числа 8-ричные. Что бы указать 10-чное число, необходимо в конец числа добавить точку. Например "16384.".

- C помощью команды DECIMALNUMBERS можно включить по умолчанию десятичные числа. Восьмиричные числа тогда начитаются с нуля, например 017666. Или можно добавить постфикс 17555o. Обратно включить по умолчанию 8-ричные числа можно командой DECIMALNUMBERS OFF.

- В одной строке может быть несколько команд. Перенос строки теперь не обязателен.

- Добавлены синонимы: RET = RTS PC, CALL = JSR PC.

- В примерах к компилятору игра Сапер.

- Команда .i8080 включает систему команд процессора Intel 8080 и можно писать программы для него. Это было сделано для написания прошивки для SMP компьютера на 8080 и ВМ1.

- Компилятор осилил исходники CP/M споткнувшись лишь на крайне странной строке "CCPSTACK:EQU $". Можно быть написать "CCPSTACK:" или "CCPSTACK EQU $", что идентично. Но не вместе же. Эту строку я поправил руками.
Last edited by alemorf on 05 Jan 2017 13:48, edited 1 time in total.
alemorf
Senior
Posts: 132
Joined: 03 Jan 2017 15:58
Location: SPb
Contact:

Re: Кросс-ассемблер для PDP11/8080 (Windows/Linux, open-s\ou

Post by alemorf »

Баг 1

Image

Баг 2

Локальные метки не правильно компилируются, и похоже они в 8-ми ричном формате и просто через функцию парсятся, например 00 и 0 я так понял одно и тоже

Баг 3

не хватает команд типа SOB RN,.-2 - приходится ставить лишнюю не нужную метку (

Баг 4

ну и как ещё идеальный вариант типа MOV #10.*2,R0 - то есть умножения перед компиляцией, деление наверно не нужно, если только например целочисленное, если не целое число, чтобы warning выдавался

(арифметику сложно встроить в синтаксис ничего не поломав, надо думать)
alemorf
Senior
Posts: 132
Joined: 03 Jan 2017 15:58
Location: SPb
Contact:

Re: Кросс-ассемблер для PDP11/8080 (Windows/Linux, open-s\ou

Post by alemorf »

И еще пожелания пользователей

 Тубро-Ассемблер Макро 7М

Turbo7M.png
Turbo7M.png (277.82 KiB) Viewed 30569 times


Last edited by alemorf on 05 Jan 2017 13:56, edited 1 time in total.
User avatar
Shaos
Admin
Posts: 23662
Joined: 09 Jan 2003 06:22
Location: Silicon Valley
Contact:

Re: Кросс-ассемблер для PDP11/8080 (Windows/Linux, open-sour

Post by Shaos »

Убрал про картинки диалог раз уж и так всё ок теперь...

P.S. В комментариях исходников всё ещё твой старый ник виднеется :roll:

P.P.S. В январе 2018 года адаптировал код для cygwin, исправил багу @NUMBER и поддержал создание образов ПЗУ для МК85

Комментарий первоначального автора по поводу лицензии см. тут (февраль 2018)

P.P.P.S. С июня 2018 прожэкт живёт в моей репе на GitLab:

https://gitlab.com/shaos/pdp11asm85

P.P.P.P.S. Архив с исходниками pdp11asm85-master.zip обновлён до версии от февраля 2024 года:

P.P.P.P.P.S. Обновлённый EXE-шник под WinXP приаттачен в архиве pdp11asm85.7z вместе с cygwin1.dll
Attachments

pdp11asm85.7z
(1.68 MiB) Downloaded 93 times

pdp11asm85-master.zip
(259.37 KiB) Downloaded 78 times

Я тут за главного - если что шлите мыло на me собака shaos точка net
alemorf
Senior
Posts: 132
Joined: 03 Jan 2017 15:58
Location: SPb
Contact:

Re: Кросс-ассемблер для PDP11/8080 (Windows/Linux, open-sour

Post by alemorf »

Если ассемблер встречает символ {, то дальше ведет себя как компилятор Си. Писал всего 5 часов, поэтому о серьзености компилятора СИ говорить рано.

Результат трансляции Си в Asm PDP11

Code: Select all

; 23 i = (a->fattrib&0x10);
MOV 0(SP), R0
MOV 11(R0), R0
ANDB #16, R0
MOVB R0, 4(SP)
; 24 j = (b->fattrib&0x10);
MOV 2(SP), R0
MOV 11(R0), R0
ANDB #16, R0
MOVB R0, 5(SP)
; 25 if(i<j) return 1;
CMPB 5(SP), 4(SP)
BHIS 1
0:
; 25 return 1;
MOV #1., R0
RET
1:
; 26 if(j<i) return 0;
CMPB 4(SP), 5(SP)
BHIS 3
2:
; 26 return 0;
MOV #0., R0
RET
3:
; 27 if(1==memcmp(a->fname, b->fname, sizeof(a->fname))) return 1;
PUSH #11
PUSH 2(SP)
PUSH 0(SP)
CALL memcmp
ADD #6., SP
CMPB R0, #1
BNE 5
4:
; 27 return 1;
MOV #1., R0
RET
5:
; 28 return 0;
MOV #0., R0
RET
User avatar
Shaos
Admin
Posts: 23662
Joined: 09 Jan 2003 06:22
Location: Silicon Valley
Contact:

Re: Кросс-ассемблер для PDP11/8080 (Windows/Linux, open-sour

Post by Shaos »

А компилятор Си для 8080 сгинул?...
Я тут за главного - если что шлите мыло на me собака shaos точка net
alemorf
Senior
Posts: 132
Joined: 03 Jan 2017 15:58
Location: SPb
Contact:

Re: Кросс-ассемблер для PDP11/8080 (Windows/Linux, open-sour

Post by alemorf »

Shaos wrote:А компилятор Си для 8080 сгинул?...
Лежит у меня. Я ниего не удалял, просто на диск скачал. Я из старого компилятора кое что для нового компилятора вытащил.

Старых компиляторов было два. Первый был закончен, но делал далеко не оптимальный код. А во втором я начал делать супер-пупер оптимизатор, который переставляет коанды местами, размещает переменные в разных регистрах. Причем по ходу кода в разных регистрах могут храниться разные переменные. Но дописать и до отладить это у меня не было времени.

Первую версию я не сохранил.

Сейчас опять делаю самый простой вараинт компиляции. Компиляция для PDP11 уже работает. Компилятор получился всего 30 Кб. Он компилирует "expression tree" (ну или типа того), который формируется при анализе C файла. Поэтому такой маленький.

Остались мелочи типа создания двоичного файла (а не текстового), выделение места в стеке под переменные, какие команды перехода использовать: far или short. Препроцессор. Всякие последовательности \r\n в строке.
User avatar
Shaos
Admin
Posts: 23662
Joined: 09 Jan 2003 06:22
Location: Silicon Valley
Contact:

Re: Кросс-ассемблер для PDP11/8080 (Windows/Linux, open-sour

Post by Shaos »

А во втором я начал делать супер-пупер оптимизатор, который переставляет коанды местами, размещает переменные в разных регистрах. Причем по ходу кода в разных регистрах могут храниться разные переменные. Но дописать и до отладить это у меня не было времени.
Ну выложил бы на гитхабе, что есть, а люди бы и дописали, и доотладили :roll:
Я тут за главного - если что шлите мыло на me собака shaos точка net
alemorf
Senior
Posts: 132
Joined: 03 Jan 2017 15:58
Location: SPb
Contact:

Re: Кросс-ассемблер для PDP11/8080 (Windows/Linux, open-sour

Post by alemorf »

Shaos wrote:
А во втором я начал делать супер-пупер оптимизатор, который переставляет коанды местами, размещает переменные в разных регистрах. Причем по ходу кода в разных регистрах могут храниться разные переменные. Но дописать и до отладить это у меня не было времени.
Ну выложил бы на гитхабе, что есть, а люди бы и дописали, и доотладили :roll:
А оно уже разлетелось по гитхабу. Вчера где то там нашел.

Я не в ту сторону оптимизировал. Конечно круто, когда программа работает быстро. Но оказалось куда важнее, что бы программа места немного занимала.
60 килобайт хватает далеко не на все хотелки. Хочется сделать еще лучше, но память уже закончилась.
User avatar
Shaos
Admin
Posts: 23662
Joined: 09 Jan 2003 06:22
Location: Silicon Valley
Contact:

Re: Кросс-ассемблер для PDP11/8080 (Windows/Linux, open-sour

Post by Shaos »

Банки памяти поддержать :)
Пока банками умеет щелкать только z88dk и то надо свой код прописывать в заглушки переключалок (я сам не пробовал, просто читал)
Я тут за главного - если что шлите мыло на me собака shaos точка net
alemorf
Senior
Posts: 132
Joined: 03 Jan 2017 15:58
Location: SPb
Contact:

Re: Кросс-ассемблер для PDP11/8080 (Windows/Linux, open-sour

Post by alemorf »

Shaos wrote:Банки памяти поддержать :)
Пока банками умеет щелкать только z88dk и то надо свой код прописывать в заглушки переключалок (я сам не пробовал, просто читал)
Переключение страниц при обращении к статическим переменным сделать не сложно. Можно даже автоматически разместить эти переменные так, что бы переключений было меньше.

А вот с указателями придется делать по медленному. Как во времена MSDOS указатель будет представлять собой 2 слова: сегмент+смещение. Ну и каждое обращение по такому указателю, это дополнительная запись в регистр страницы.

Либо как было сделано для микроконтроллеров AVR. Добавить номер страницы в тип указателя.

uint8_t _page1[64]
void _page1* a
unsigned _page2* _page0* b;
User avatar
Shaos
Admin
Posts: 23662
Joined: 09 Jan 2003 06:22
Location: Silicon Valley
Contact:

Re: Кросс-ассемблер для PDP11/8080 (Windows/Linux, open-sour

Post by Shaos »

лучше как в досе - тип указателя far (и указатель становится 4 байта вместо 2), как минимум это логично (а указывать страницы при создании указателя - не очень)
Я тут за главного - если что шлите мыло на me собака shaos точка net
alemorf
Senior
Posts: 132
Joined: 03 Jan 2017 15:58
Location: SPb
Contact:

Re: Кросс-ассемблер для PDP11/8080 (Windows/Linux, open-sour

Post by alemorf »

Shaos wrote:лучше как в досе - тип указателя far (и указатель становится 4 байта вместо 2), как минимум это логично (а указывать страницы при создании указателя - не очень)
Ну это скорость уменьшит в 3 раза.

Сейчас *a = 0xAAAA; компилируется в

mov #0xAAAA, @2(SP)

а будет

mov 2(SP), R0
mov 4(SP), SYS_PAGE_REG
mov #0xAAAA, (R0)
alemorf
Senior
Posts: 132
Joined: 03 Jan 2017 15:58
Location: SPb
Contact:

Re: Кросс-ассемблер для PDP11/8080 (Windows/Linux, open-sour

Post by alemorf »

Сегодня потратил единственный час на добавление дизассемблера. Надо как то проверять, что там компилятор накомпилировал.

Code: Select all

0023 0006                      		//10 uint16_t* a = (uint16_t*)0x4000;
0023 0006 017266 040000 000002 		mov #16384, 2(SP)
0023 000C                      		//12 if(*a) test(23);
0023 000C 016700 000002        		mov @2(SP), R0
0023 0010 005700               		tst R0
0023 0012 001400               		beq 5
0023 0014                      		//12 test(23);
0023 0014 017264 000027        		mov #23, -(SP)
0023 0018 004772 000000        		jsr PC, test
0023 001C 067260 000002        		add #2, SP
0023 0020                      		5:
0023 0020                      		//13 i=0x2000;
0023 0020 017266 020000 000004 		mov #8192, 4(SP)
0023 0026                      		4:
0023 0026                      		//15 do {
0023 0026                      		//16 *a = 0xAAAA;
0023 0026 017267 125252 000002 		mov #43690, @2(SP)
0023 002C                      		//17 a++;
0023 002C 067266 000002 000002 		add #2, 2(SP)
0023 0032                      		//18 i--;
0023 0032 005366 000004        		dec 4(SP)
0023 0036                      		//19 } while(i);
0023 0036 016600 000004        		mov 4(SP), R0
0023 003A 005700               		tst R0
0023 003C 001000               		bne 4
TST уберу потом. И регистровые переменные сделаю.
User avatar
Shaos
Admin
Posts: 23662
Joined: 09 Jan 2003 06:22
Location: Silicon Valley
Contact:

Re: Кросс-ассемблер для PDP11/8080 (Windows/Linux, open-sour

Post by Shaos »

alemorf wrote:
Shaos wrote:лучше как в досе - тип указателя far (и указатель становится 4 байта вместо 2), как минимум это логично (а указывать страницы при создании указателя - не очень)
Ну это скорость уменьшит в 3 раза.

Сейчас *a = 0xAAAA; компилируется в

mov #0xAAAA, @2(SP)

а будет

mov 2(SP), R0
mov 4(SP), SYS_PAGE_REG
mov #0xAAAA, (R0)
Ну так это от автора компилируемой программы зависит - если поставил ключевое слово far, то ожидай что будет чуть медленнее, а если хочешь быстрее - не ставь far :)
Но это наверное тут оффтоп :)

P.S. Форк C8080 вроде нашел - форкнул себе...
Я тут за главного - если что шлите мыло на me собака shaos точка net
Post Reply