Наверное всё-таки на последних версиях C++ надо этот макро-ассемблер писать - назвать его скажем TRIADORA
Кроме макросов поддержать ключевые слова ORG, EQU, INCLUDE и ALIGN (для выравнивания на границу сегментов надо будет писать ALIGN 27 при этом возможная дырка будет заполнена нулевой командой ничегонеделанья RR 0). Всяких там DB небудет т.к. память данных нет возможности инициализировать кроме как писать туда через EX инструкции обращения к памяти - переменные объявлять адресами через EQU (я так для пиков пишу уже много лет точно зная где у меня та или иная переменная сидит).
Кроме того на примере выше видно присутствие ключевых слов SEG и OFF, которые из константы или метки (которая суть тоже константа, которая становится известной на поздних проходах) выделяют старшую триаду (SEGment) и младшую триаду (OFFset). Также внутри макросов будет возможным указывать локальные (для макроса) метки через ключевое слово LOCAL:
При кодогенерации при каждом использовании такого макроса будет ставиться метка с уникальным именем (с добавлением некоего уникального номера), например
будет преобразовано при первом проходе в
Возможно надо будет ещё поддержать ключевые слова FILE и LINE для отслеживания оригинальных источников строчек кода для корректного сообщения об ошибке в случае проблем с ассемблированием.
Ну и в дальнейшем надо будет добавить условную компиляцию с ключевыми словами IF, ELSE, ENDIF, NOT, AND, OR, EQ, NE, LT, LE, GT, GE ( всё по мотивам MASM ; )
А может в условия ещё добавить троичную инверсию INV ?
P.S. IFDEF, IFNDEF и ELSEIF ненужны - планирую обойтись одним IF. Опция командной строки -DNAME для ассемблера будет означать тоже самое что и NAME EQU 1 внутри и далее можно писать IF NAME или IF NOT NAME и т.д. (отсутствие константы NAME будет равносильно 0). Плюс директива ERROR чтобы прервать ассемблирование с текстовым сообщением...
P.P.S. Обновлённый заголовочный файл для триадоры в соответствии с новыми веяньями:
TRIADOR3.INC | | |
| Code: ; TRIADOR-3 definitions for assembler TRIADORA v1.0 ; Created in May 2020 by Alexander A. Shabarshin <me@shaos.net> ; This file is considered PUBLIC DOMAIN (intentionally put there by creator)
; 1-trit balanced ternary numbers
N EQU -1 O EQU 0 P EQU 1
; 2-trit balanced ternary numbers
NN EQU -4 NO EQU -3 NP EQU -2 ON EQU -1 OO EQU 0 OP EQU 1 PN EQU 2 PO EQU 3 PP EQU 4
; 3-trit balanced ternary numbers
NNN EQU -13 NNO EQU -12 NNP EQU -11 NON EQU -10 NOO EQU -9 NOP EQU -8 NPN EQU -7 NPO EQU -6 NPP EQU -5 ONN EQU -4 ONO EQU -3 ONP EQU -2 OON EQU -1 OOO EQU 0 OOP EQU 1 OPN EQU 2 OPO EQU 3 OPP EQU 4 PNN EQU 5 PNO EQU 6 PNP EQU 7 PON EQU 8 POO EQU 9 POP EQU 10 PPN EQU 11 PPO EQU 12 PPP EQU 13
; Ternary logic constants
NEG EQU -1 UNK EQU 0 POS EQU 1
; >>>>> SKIP MACROS
IFR4LEZ EQU -13 IFR4NEZ EQU -12 IFR4GEZ EQU -11 IFR3LEZ EQU -10 IFR3NEZ EQU -9 IFR3GEZ EQU -8 IFR2LEZ EQU -7 IFR2NEZ EQU -6 IFR2GEZ EQU -5 IFR1LEZ EQU -4 IFR1NEZ EQU -3 IFR1GEZ EQU -2 IFBORROW EQU -1 IFNOOVER EQU 0 IFCARRY EQU 1 IFR1LTZ EQU 2 IFR1EQZ EQU 3 IFR1GTZ EQU 4 IFR2LTZ EQU 5 IFR2EQZ EQU 6 IFR2GTZ EQU 7 IFR3LTZ EQU 8 IFR3EQZ EQU 9 IFR3GTZ EQU 10 IFR4LTZ EQU 11 IFR4EQZ EQU 12 IFR4GTZ EQU 13
; Long jump to label L JMP MACRO L R1 SEG L RR -13 JP OFF L ENDM
; Refresh R13 with current segment identifier RFR MACRO LOCAL L R1 SEG L RR -13 L: ENDM
; Decrement R1 with updating flag C DECR1 MACRO RR -1 ENDM
; No operation (OOOOO) NOOP MACRO RR 0 ENDM
; Increment R1 with updating flag C INCR1 MACRO RR 1 ENDM
; >>>>> EXTENDED INSTRUCTIONS
; Halt and catch fire HLT MACRO EX -13 ENDM
; Program EX using R1,R2,R3 and R4 as identifier of EX command to program PEX MACRO EX 0 ENDM
; Indirect jump to R13,R1 with storing PC+1 to R12,R11 JPI MACRO EX 13 ENDM
; >>>>> BINARY TRITWISE OPERATIONS
CMP MACRO EX 1 ENDM
MIN MACRO EX 2 ENDM
MAX MACRO EX 3 ENDM
MUL MACRO EX 4 ENDM
SUM MACRO EX 5 ENDM
CON MACRO EX 6 ENDM
; >>>>> PREDEFINED PERMUTATIONS
CLC MACRO EX 7 ENDM
RLC MACRO EX 8 ENDM
RRC MACRO EX 9 ENDM
; >>>>> DATA MEMORY ACCESS
; Write R2,R1 to data memory address R4,R3 WMM MACRO EX 10 ENDM
; Read data memory from address R4,R3 and store lower triade to R1 RML MACRO EX 11 ENDM
; Read data memory from address R4,R3 and store higher triade to R1 RMH MACRO EX 12 ENDM
; Read data memory from address A and store value to R2,R1 RMA MACRO A R1 SEG A RR -4 R1 OFF A RR -3 RMH RR -2 RML ENDM
; Write R2,R1 to data memory address A WMA MACRO A R1 SEG A RR -4 R1 OFF A RR -3 WMM ENDM
; Write constant C to data memory address A WMC MACRO A C R1 SEG A RR -4 R1 OFF A RR -3 R1 SEG C RR -2 R1 OFF C WMM ENDM
; >>>>> SUBROUTINES MACROS (SP=R10,R9)
; subroutine is called by CALL label
; if subrouting is not calling anything else then it can just do RET at the end
; if subrouting is calling something else (including itself) while working ; then it should do PUSH in the beginning to store current R12,R11 on the stack ; and it should do RETURN at the end to return to proper address from the stack
; to store pair of registers on the stack use PUSHRR and POPRR to retrieve them
CALL MACRO A R1 SEG A RR -13 R1 OFF A JPI ENDM
RET MACRO RR 12 RR -13 RR 11 JPI ENDM
SSP MACRO A R1 SEG A RR -10 R1 OFF A RR -9 ENDM
PUSH MACRO RR 10 RR -4 RR 9 RR -3 RR 12 RR -2 RR 11 WMM RR 9 RR -1 RR -9 RR 10 SK IFNOOVER RR -1 RR -10 ENDM
RETURN MACRO RR 9 RR 1 RR -9 RR -3 RR 10 SK IFNOOVER RR 1 RR -10 RR -4 RMH RR -13 RML JPI ENDM
PUSHRR MACRO H L RR 10 RR -4 RR 9 RR -3 RR H RR -2 RR L WMM RR 9 RR -1 RR -9 RR 10 SK IFNOOVER RR -1 RR -10 ENDM
POPRR MACRO H L RR 9 RR 1 RR -9 RR -3 RR 10 SK IFNOOVER RR 1 RR -10 RR -4 RMH RR -H RML ; IF L NE 1 RR -L ; ENDIF ENDM
| |
| | |
P.P.P.S. IF в последнем макросе закомментирован, т.к. в первой версии ассемблера я не планирую иметь условную компиляцию (в этом конкретном макросе условная компиляция предотвратила бы декремент R1, если макрос используется для вытаскивания из стека регистров R2,R1 в виде POPRR 2 1 и кстати в PUSHRR тоже надо бы что-то выдумать на тему R2,R1)
P.P.P.P.S. (добавлено 17 мая 2020 года) ещё можно программно нагенерить макросов с равно (сделав символ '=' разрешённым в именах макросов) типа R1=R2, R13=NOP и даже сделать макросы умеющие скажем R13=-13 или R5=+5 путём искусственной вставки пробела при первом проходе перед символами '-' или '+' если его там небыло, тогда R13=-13 будет воспринято как R13= -13 и сассемблируется вот таким макросом: