Автор |
Сообщение |
|
|
Заголовок сообщения: |
Re: EQUINOX: Ассемблер и Forth |
|
|
продолжаю начатое. Следующий шаг - написание и проверка функций BIOS - ввод с клавиатуры и печать на экран Код: ; -------------------------------------- ; (c) 2012 WingLion ; -------------------------------------- ; файл предназначен для инклюда ; в исходники приложений для процессора EQUINOX ORGS bios_place ;------------------------- ; BIOS для форт-системы на процессоре EQUINOX ;------------------------- ; константы - адреса целевой системы - зависят от HARDWARE screen_data = 1200h ; данные экрана в формате символ.атрибут screen_mode = 1000h ; построчный режим экрана - ; - размер символа,длина строки в символах,адрес строки,адрес знакогенератора screen_zg = 1C00h ; место знакогенератора 8x8 точек ; просто константы screen_size = 0800h kbd_port = 04001h ; порт ввода с клавиатуры ;------------------------- ; системные переменные ;------------------------- ; получить адрес на экране SCR_PLACE: _LIT screen_data SCR_PL = (SCR_PLACE-begin)/2 + 1 _RET_ ;------------------------- ; сохранить адрес на экране SET_SCR_PLACE: _LIT_PRISW SCR_PL _RET_ ;------------------------- ; получить текущй цвет GET_COLOR: _LIT 07000h COLOR = (GET_COLOR-begin)/2 + 1 _RET_ ;------------------------- ; сохранить текущий цвет SET_COLOR: _LIT_PRISW COLOR _RET_ ;------------------------- ; печатать символ TYPE_SYMBOL: _CALL SCR_PLACE ; взять место _SWAP _OVER _PRISW ; напечатать _INC ; перейти на следующее место _DUP _LIT screen_data+screen_size _XOR ; если не достигли конца _JNZ SET_SCR_PLACE ; сохраняем положение ;------------------------- ; вот здесь надо вставлять функцию скроллинга экрана, если она нужна - а пока без нее ;------------------------- FROM_SCR_BEGIN: _LIT screen_data ; иначе устанавливаем позицию сначала экрана _JMP SET_SCR_PLACE ;------------------------- ; печать строки, заканчивающейся нулем, адрес которой лежит на стеке возвратов ; с возвратом на следующий адрес за строкой TYPE_STRING: _fromR ; получить адрес символа _DUP _toR ; копию вернуть на стек возвратов _RAZIM ; получить символ _AND 0FFh ; выделить первый байт и проверить на ноль _DUP _JZ TYPE_END ; если ноль, то на выход _CALL TYPE_SYMBOL ; иначе - печатать _fromR ; получить адрес следующего символа _DUP _toR ; вернуть копию на стек возвратов _RAZIM ; получить символ _BSWAP ; второй символ в старшей части слова _AND 0FFh ; выделить и проверить на ноль _DUP _JZ TYPE_END ; если ноль; то на выход _CALL TYPE_SYMBOL ; иначе - печатать _fromR ; следующие два символа строки _INC _toR _JMP TYPE_STRING ; зациклить печать _compile_ TYPE_END: _fromR ; конец _INC _toR _RET ;------------------------- INIT_SCREEN: _CALL FROM_SCR_BEGIN _LIT 0700h _CALL SET_COLOR ; _CALL CLS ; _RET_ _compile_ ;------------------------- CLS: _LIT screen_size _compile_ CLS_loop: _toR _LIT " " _CALL TYPE_SYMBOL _fromR _DEC _DUP _JNZ CLS_loop _JMP FROM_SCR_BEGIN ;------------------------- ; ввод кода клавиши без ожидания ; железный контроллер выдает код сразу в ascii, поэтому перекодировка не нужна INKEY: _LIT@ kbd_port _DUP _AND 08000h ; проверка, что было нажатие _JZ set_false ; если не было, выйти с установкой флага false _compile_ set_true: _TRUE ; иначе установить true _RET_ set_false: _DROP _FALSE _RET_ ;------------------------- WAIT_KEY: _CALL INKEY DW 0,0,0,0 ; резерв _JZ WAIT_KEY _RET_ ;------------------------- p.s. Проверена только часть этих функций p.p.s. Зачем пишу непонятные закорючки? -- Чтобы не потерялось, и чтобы было полезно кому-нибудь, кто решится использовать EQUINOX для чего-нибудь.
продолжаю начатое.
Следующий шаг - написание и проверка функций BIOS - ввод с клавиатуры и печать на экран
[code] ; -------------------------------------- ; (c) 2012 WingLion ; -------------------------------------- ; файл предназначен для инклюда ; в исходники приложений для процессора EQUINOX ORGS bios_place ;------------------------- ; BIOS для форт-системы на процессоре EQUINOX ;------------------------- ; константы - адреса целевой системы - зависят от HARDWARE screen_data = 1200h ; данные экрана в формате символ.атрибут screen_mode = 1000h ; построчный режим экрана - ; - размер символа,длина строки в символах,адрес строки,адрес знакогенератора screen_zg = 1C00h ; место знакогенератора 8x8 точек ; просто константы screen_size = 0800h kbd_port = 04001h ; порт ввода с клавиатуры ;------------------------- ; системные переменные ;------------------------- ; получить адрес на экране SCR_PLACE: _LIT screen_data SCR_PL = (SCR_PLACE-begin)/2 + 1 _RET_ ;------------------------- ; сохранить адрес на экране SET_SCR_PLACE: _LIT_PRISW SCR_PL _RET_ ;------------------------- ; получить текущй цвет GET_COLOR: _LIT 07000h COLOR = (GET_COLOR-begin)/2 + 1 _RET_ ;------------------------- ; сохранить текущий цвет SET_COLOR: _LIT_PRISW COLOR _RET_ ;------------------------- ; печатать символ TYPE_SYMBOL: _CALL SCR_PLACE ; взять место _SWAP _OVER _PRISW ; напечатать _INC ; перейти на следующее место _DUP _LIT screen_data+screen_size _XOR ; если не достигли конца _JNZ SET_SCR_PLACE ; сохраняем положение ;------------------------- ; вот здесь надо вставлять функцию скроллинга экрана, если она нужна - а пока без нее ;------------------------- FROM_SCR_BEGIN: _LIT screen_data ; иначе устанавливаем позицию сначала экрана _JMP SET_SCR_PLACE ;------------------------- ; печать строки, заканчивающейся нулем, адрес которой лежит на стеке возвратов ; с возвратом на следующий адрес за строкой TYPE_STRING: _fromR ; получить адрес символа _DUP _toR ; копию вернуть на стек возвратов _RAZIM ; получить символ _AND 0FFh ; выделить первый байт и проверить на ноль _DUP _JZ TYPE_END ; если ноль, то на выход _CALL TYPE_SYMBOL ; иначе - печатать _fromR ; получить адрес следующего символа _DUP _toR ; вернуть копию на стек возвратов _RAZIM ; получить символ _BSWAP ; второй символ в старшей части слова _AND 0FFh ; выделить и проверить на ноль _DUP _JZ TYPE_END ; если ноль; то на выход _CALL TYPE_SYMBOL ; иначе - печатать _fromR ; следующие два символа строки _INC _toR _JMP TYPE_STRING ; зациклить печать _compile_ TYPE_END: _fromR ; конец _INC _toR _RET ;------------------------- INIT_SCREEN: _CALL FROM_SCR_BEGIN _LIT 0700h _CALL SET_COLOR ; _CALL CLS ; _RET_ _compile_ ;------------------------- CLS: _LIT screen_size _compile_ CLS_loop: _toR _LIT " " _CALL TYPE_SYMBOL _fromR _DEC _DUP _JNZ CLS_loop _JMP FROM_SCR_BEGIN ;------------------------- ; ввод кода клавиши без ожидания ; железный контроллер выдает код сразу в ascii, поэтому перекодировка не нужна INKEY: _LIT@ kbd_port _DUP _AND 08000h ; проверка, что было нажатие _JZ set_false ; если не было, выйти с установкой флага false _compile_ set_true: _TRUE ; иначе установить true _RET_ set_false: _DROP _FALSE _RET_ ;------------------------- WAIT_KEY: _CALL INKEY DW 0,0,0,0 ; резерв _JZ WAIT_KEY _RET_ ;-------------------------[/code]
p.s. Проверена только часть этих функций
p.p.s. Зачем пишу непонятные закорючки? -- Чтобы не потерялось, и чтобы было полезно кому-нибудь, кто решится использовать EQUINOX для чего-нибудь.
|
|
|
|
Добавлено: Ср мар 28, 2012 22:08 |
|
|
|
|
|
Заголовок сообщения: |
Re: EQUINOX: Ассемблер и Forth |
|
|
Ну, прошу прощения сегодня ведь равноденствие ... какие-то ассоциации сработали
Ну, прошу прощения сегодня ведь равноденствие ... какие-то ассоциации сработали
|
|
|
|
Добавлено: Ср мар 21, 2012 18:57 |
|
|
|
|
|
Заголовок сообщения: |
Re: EQUINOX: Ассемблер и Forth |
|
|
Непонятно только, какое отношение имеет ссылка к данному топику. Хотя, понятно, что никакого... И ничего похожего в названии не увидел, кроме некоторых букв... Но букв мало. Неудивительно, что некоторые у разных названий совпадают.
Непонятно только, какое отношение имеет ссылка к данному топику. Хотя, понятно, что никакого... И ничего похожего в названии не увидел, кроме некоторых букв... Но букв мало. Неудивительно, что некоторые у разных названий совпадают.
|
|
|
|
Добавлено: Ср мар 21, 2012 17:57 |
|
|
|
|
|
Заголовок сообщения: |
Re: EQUINOX: Ассемблер и Forth |
|
|
похожее название http://www.ixbt.com/news/hard/index.shtml?15/63/26
|
|
|
|
Добавлено: Ср мар 21, 2012 14:22 |
|
|
|
|
|
Заголовок сообщения: |
Re: EQUINOX: Ассемблер и Forth |
|
|
--- удалено ввиду бесполезности находившегося здесь кода ---
--- удалено ввиду бесполезности находившегося здесь кода ---
|
|
|
|
Добавлено: Вт мар 20, 2012 20:32 |
|
|
|
|
|
Заголовок сообщения: |
Re: EQUINOX: Ассемблер и Forth |
|
|
Следующим шагом должно быть написание минимальной форт-системы, которая выполняет цикл:
1. Ввести строку из устройства ввода (клавиатура/блок данных из ПЗУ/ и т.п.) 2. Интерпретировать введенную строку. 3. Перейти к 1. В процессе интерпретации могут быть откомпилированы и запущены иные программы, вплоть до нового цикла интерпретации, поэтому, первичный цикл не нужно нагружать никакими излишествами. Он должен быть максимально прост.
Следующим шагом должно быть написание минимальной форт-системы, которая выполняет цикл:
1. Ввести строку из устройства ввода (клавиатура/блок данных из ПЗУ/ и т.п.) 2. Интерпретировать введенную строку. 3. Перейти к 1. В процессе интерпретации могут быть откомпилированы и запущены иные программы, вплоть до нового цикла интерпретации, поэтому, первичный цикл не нужно нагружать никакими излишествами. Он должен быть максимально прост.
|
|
|
|
Добавлено: Вт мар 20, 2012 19:59 |
|
|
|
|
|
Заголовок сообщения: |
Re: EQUINOX: Ассемблер и Forth |
|
|
Следующий код является тестовой программой для процессора EQUINOX 16 проверяется работа всех команд процессора путем записи в стек данных, выполнения команды и сравнения результатов с тем, что должно быть: Код: ; ; программа для тестирования процессора EQUINOX 16 ; проверка арифметическо-логических команд, ; команд работы с памятью и стеком возвратов, ; а так же ассемблерных макросов для их реализации ;
.386 .MODEL tiny .CODE
; LOCALS
include equinox.asm ; макро-определения для форт-команд
; -- тут можно и другие макросы вставлять
_TEST MACRO data,name; на стеке два значения, если они не равны, программа должна быть остановлена, иначе продолжается дальше _compile_ _LIT data _XOR ; _compile_ _BRAN name&_1 _compile_ _STOP _compile_ name&_1: _DROP _compile_ ENDM
_RET_ MACRO _RET _compile_ ENDM
ORG 100h
test_test proc near LOCALS begin: ORGS 000h ; начало ; виртуальное начало с адреса 0000h, для TASM-a - 0100h, поэтому в макросах адреса уменьшаются на 100h nnn = 000 _NOP ; традиционно начинаю с NOP-a, чтобы можно было заглушить программу, вставив сюда STOP или RET
_CALL test_xdup ; проверка группы команд XDUP _compile_ _CALL test_xswap ; проверка группы команд XSWAP _CALL test_xdrop ; проверка группы команд XSWAP _CALL test_nibbles ; проверка @ ! >R R> ; ------------------------------ ; _STOP xx1: _ZERO _BRAN xx1 ;------------------------------- _compile_ test_xdup: _ZERO ; 0 _DUP ; 0 0 _DEC ; 0 -1 _OVER ; 0 -1 0 _TEST 0,t1 ; 0 -1 ; _DROP ; 0 -1 _NIP ; -1 _TEST -1,t20 ; _MONE _TEST -1,t2 _RET_ ; --------------------------- _compile_ test_xswap: ; _SWAP _INC _DEC _NEG _INV _MUL _LCONV _BSWAP _LSHIFT _RSHIFT ; ---------------------- SWAP _LIT 1 _LIT 2 _SWAP
_TEST 1,t3 _TEST 2,t4 ; ---------------------- INC _LIT 2 _INC _TEST 3,t5 _LIT 4 _DEC _TEST 3,t6 ; ---------------------- DEC _LIT 64 _NEG _TEST -64,t7 ; ---------------------- NEG _LIT 0AA55h _INV _TEST 055AAh,t18 ; ---------------------- INV _LIT 0CC33h _INV _TEST 033CCh,t8 ; ---------------------- MUL _LIT 4 _LIT 5 _MUL _TEST 20,t9 _TEST 0,t10 _LIT 1100h _LIT 300h _MUL _TEST 0,t11 _TEST 33h,t12 ; ---------------------- LCONV _LIT 7 _LCONV _TEST 0,t13 _LIT 0 _LCONV _TEST -1,t14 ; ---------------------- BSWAP _LIT 051A1h _BSWAP _TEST 0A151h,t15 ; ---------------------- LSHIFT _LIT 0700h _RSHIFT _TEST 0380h,t16 ; ---------------------- RSHIFT _LIT 0700h _LSHIFT _TEST 0E00h,t17 ; ---------------------- _RET_ ; ---------------------- _compile_ test_xdrop: ; ---------------------- ; ---------------------- _DROP _CALL set_literals _DROP _TEST 3,t20m _TEST 2,t21 _TEST 1,t22 ; ---------------------- _NIP _CALL set_literals _NIP _TEST 4,t23 _TEST 2,t24 _TEST 1,t25 ; ---------------------- _ADD _CALL set_literals _ADD _TEST 7,t26 _TEST 2,t27 _TEST 1,t28 ; ---------------------- _SUB _CALL set_literals _SUB _TEST -1,t29 _TEST 2,t30 _TEST 1,t31 ; ---------------------- _AND _CALL set_literals _AND _TEST 0,t32 _TEST 2,t33 _TEST 1,t34 ; ---------------------- _OR _CALL set_literals _OR _TEST 7,t35 _TEST 2,t36 _TEST 1,t37 ; ---------------------- _XOR _CALL set_literals _XOR _TEST 7,t38 _TEST 2,t39 _TEST 1,t40 ; ---------------------- _NAND _CALL set_literals _NAND _TEST -1,t41 _TEST 2,t42 _TEST 1,t43 ; ---------------------- _ADC ; ---------------------- _SBC _RET_ ; ---------------------- set_literals: _LIT 1 _LIT 2 _LIT 3 _LIT 4 _RET_ ; ---------------------- test_nibbles: ; ---------------------- @ ! _LIT 0AAh _LIT 1000h _PRISW _LIT 1000h _RAZIM _TEST 0AAh
_LIT 1000h _CALL inc_ram _LIT 1000h _RAZIM _TEST 0ABh,t48
_LIT 1000h _CALL inc_ram _LIT 1000h _RAZIM _TEST 0ACh,t49 ; ---------------------- >R R> _CALL set_literals _toR _toR _toR _TEST 1,t44 _fromR _TEST 2,t45 _fromR _TEST 3,t46 _fromR _TEST 4,t47 _RET_
; ---------------------- ; ---------------------- ; ---------------------- nops 12,13,14 ; ---------------------- ; ---------------------- ; ---------------------- ; ---------------------- ; ----------------------
; увеличить на единицу содержимое ячейки памяти (addr --> ) inc_ram: _DUP _RAZIM _INC _SWAP _PRISW _RET_
endp
end begin
Тест был откомпилирован, записан в память, подключенную к процессору и успешно прогнан в симуляторе. Возможно, проверено не все и не все нюансы, но можно с уверенностью утверждать, что работоспособность процессора проверена на 90+ процентов...
Следующий код является тестовой программой для процессора EQUINOX 16 проверяется работа всех команд процессора путем записи в стек данных, выполнения команды и сравнения результатов с тем, что должно быть:
[code]; ; программа для тестирования процессора EQUINOX 16 ; проверка арифметическо-логических команд, ; команд работы с памятью и стеком возвратов, ; а так же ассемблерных макросов для их реализации ;
.386 .MODEL tiny .CODE
; LOCALS
include equinox.asm ; макро-определения для форт-команд
; -- тут можно и другие макросы вставлять
_TEST MACRO data,name; на стеке два значения, если они не равны, программа должна быть остановлена, иначе продолжается дальше _compile_ _LIT data _XOR ; _compile_ _BRAN name&_1 _compile_ _STOP _compile_ name&_1: _DROP _compile_ ENDM
_RET_ MACRO _RET _compile_ ENDM
ORG 100h
test_test proc near LOCALS begin: ORGS 000h ; начало ; виртуальное начало с адреса 0000h, для TASM-a - 0100h, поэтому в макросах адреса уменьшаются на 100h nnn = 000 _NOP ; традиционно начинаю с NOP-a, чтобы можно было заглушить программу, вставив сюда STOP или RET
_CALL test_xdup ; проверка группы команд XDUP _compile_ _CALL test_xswap ; проверка группы команд XSWAP _CALL test_xdrop ; проверка группы команд XSWAP _CALL test_nibbles ; проверка @ ! >R R> ; ------------------------------ ; _STOP xx1: _ZERO _BRAN xx1 ;------------------------------- _compile_ test_xdup: _ZERO ; 0 _DUP ; 0 0 _DEC ; 0 -1 _OVER ; 0 -1 0 _TEST 0,t1 ; 0 -1 ; _DROP ; 0 -1 _NIP ; -1 _TEST -1,t20 ; _MONE _TEST -1,t2 _RET_ ; --------------------------- _compile_ test_xswap: ; _SWAP _INC _DEC _NEG _INV _MUL _LCONV _BSWAP _LSHIFT _RSHIFT ; ---------------------- SWAP _LIT 1 _LIT 2 _SWAP
_TEST 1,t3 _TEST 2,t4 ; ---------------------- INC _LIT 2 _INC _TEST 3,t5 _LIT 4 _DEC _TEST 3,t6 ; ---------------------- DEC _LIT 64 _NEG _TEST -64,t7 ; ---------------------- NEG _LIT 0AA55h _INV _TEST 055AAh,t18 ; ---------------------- INV _LIT 0CC33h _INV _TEST 033CCh,t8 ; ---------------------- MUL _LIT 4 _LIT 5 _MUL _TEST 20,t9 _TEST 0,t10 _LIT 1100h _LIT 300h _MUL _TEST 0,t11 _TEST 33h,t12 ; ---------------------- LCONV _LIT 7 _LCONV _TEST 0,t13 _LIT 0 _LCONV _TEST -1,t14 ; ---------------------- BSWAP _LIT 051A1h _BSWAP _TEST 0A151h,t15 ; ---------------------- LSHIFT _LIT 0700h _RSHIFT _TEST 0380h,t16 ; ---------------------- RSHIFT _LIT 0700h _LSHIFT _TEST 0E00h,t17 ; ---------------------- _RET_ ; ---------------------- _compile_ test_xdrop: ; ---------------------- ; ---------------------- _DROP _CALL set_literals _DROP _TEST 3,t20m _TEST 2,t21 _TEST 1,t22 ; ---------------------- _NIP _CALL set_literals _NIP _TEST 4,t23 _TEST 2,t24 _TEST 1,t25 ; ---------------------- _ADD _CALL set_literals _ADD _TEST 7,t26 _TEST 2,t27 _TEST 1,t28 ; ---------------------- _SUB _CALL set_literals _SUB _TEST -1,t29 _TEST 2,t30 _TEST 1,t31 ; ---------------------- _AND _CALL set_literals _AND _TEST 0,t32 _TEST 2,t33 _TEST 1,t34 ; ---------------------- _OR _CALL set_literals _OR _TEST 7,t35 _TEST 2,t36 _TEST 1,t37 ; ---------------------- _XOR _CALL set_literals _XOR _TEST 7,t38 _TEST 2,t39 _TEST 1,t40 ; ---------------------- _NAND _CALL set_literals _NAND _TEST -1,t41 _TEST 2,t42 _TEST 1,t43 ; ---------------------- _ADC ; ---------------------- _SBC _RET_ ; ---------------------- set_literals: _LIT 1 _LIT 2 _LIT 3 _LIT 4 _RET_ ; ---------------------- test_nibbles: ; ---------------------- @ ! _LIT 0AAh _LIT 1000h _PRISW _LIT 1000h _RAZIM _TEST 0AAh
_LIT 1000h _CALL inc_ram _LIT 1000h _RAZIM _TEST 0ABh,t48
_LIT 1000h _CALL inc_ram _LIT 1000h _RAZIM _TEST 0ACh,t49 ; ---------------------- >R R> _CALL set_literals _toR _toR _toR _TEST 1,t44 _fromR _TEST 2,t45 _fromR _TEST 3,t46 _fromR _TEST 4,t47 _RET_
; ---------------------- ; ---------------------- ; ---------------------- nops 12,13,14 ; ---------------------- ; ---------------------- ; ---------------------- ; ---------------------- ; ----------------------
; увеличить на единицу содержимое ячейки памяти (addr --> ) inc_ram: _DUP _RAZIM _INC _SWAP _PRISW _RET_
endp
end begin [/code]
Тест был откомпилирован, записан в память, подключенную к процессору и успешно прогнан в симуляторе.
Возможно, проверено не все и не все нюансы, но можно с уверенностью утверждать, что работоспособность процессора проверена на 90+ процентов...
|
|
|
|
Добавлено: Вт мар 20, 2012 18:26 |
|
|
|
|
|
Заголовок сообщения: |
EQUINOX: Ассемблер и Forth |
|
|
A теперь маленький фокус: Представленный ниже код есть не что иное, как ассемблер для Форт-процессора EQUINOX 16, использующий самый обычный "старинный" борландовский TASM версии 3.1 Спрашивать, почему TASM, а не FORTH - не нужно. Ибо такова селяви. Чтобы написать программу для EQUINOX на TASM-e надо всего лишь включить данный код в начало файла с исходником и использовать описанные макросы (начинающиеся с символа подчеркивания) как форт-команды. Код: ; -------------------------------------- ; 28.03.2012 vers 1.02 ; макро-определения для форт-процессора EQUINOX 16 ; (c) 2012 WingLion ; для использования с турбоассемблером TASM v3.1 ; -------------------------------------- ; ; Справка: система команд процессора EQUINOX (март 2012 года) ; ; команда код описание ; NOP - 0 - нет операции - загрузка следующего командного слова ; RET - 1 - возврат из подпрограммы ; CALL - 2 L - вызов подпрограммы ; BRAN - 3 L - условный переход по нулю в стеке данных ; LIT - 4 L - загрузка литерала ; ! - 5 - стандартное фортовое "присвоить" ; @ - 6 - стандартное фортовое "разыменовать" ; STOP - 7 - остановить процесс исполнения (HALT) ; >R - 8 - переместить число со стека данных на стек возвратов ; R> - 9 - переместить число со стека возвратов на стек данных ; XDUP - А p - АЛУ операция с уменьшением глубины стека ; XSWAP B p - АЛУ операция с неизменной глубиной стека ; XDROP C p - АЛУ операьия с увеличением глубины стека ; NOP13 D - оперция не определена ; NOP14 E - оперция не определена ; NOP15 F - оперция не определена ; ; - L - требует литерала ; - p - префиксная команда
; --- вспомогательные макросы ---
; организация компиляции на виртуальном адресе addr
ORGS MACRO addr
NN = 0 ; -- сброс числа нибблов NL = 0 ; -- сброс числа литералов NMAX = 4 ; максимальное число нибблов в слове и литералов в команде WD = 0 ; "накопитель нибблов" - текущее слово для компиляции
A1 = (100h + addr*2) ; нулевой адрес в 100h
ORG A1 ; самый обыкнoвенный ORG
ENDM
; компиляция слова (при необходимости можно переставить байты)
XDW MACRO data
;B1 = data / 256 ; старший ;B2 = data - (B1*256) ; младший ; DB B1 ; DB B2
DW data
ENDM
; компиляция литералов - размещение литералов после командного слова
LITS MACRO IF NL GT 0 XDW L1 ENDIF IF NL GT 1 XDW L2 ENDIF IF NL GT 2 XDW L3 ENDIF IF NL GT 3 XDW L4 ENDIF NL = 0 ENDM
; предкомпиляция литералов - размещение литералов в переменных ; для последующей компиляции после командного слова
LITERAL MACRO addr IF NL EQ 0 L1 = addr ENDIF IF NL EQ 1 L2 = addr ENDIF IF NL EQ 2 L3 = addr ENDIF IF NL EQ 3 L4 = addr ENDIF NL = NL + 1 ENDM
; компиляция четырехбитной команды
NIBBLE MACRO N ; размещение компилируемого ниббла в "накопителе нибблов" для последующей компиляции, когда их наберется 4 штуки WD = WD*16 + N NN = NN+1 ; счетчик нибблов IF NN EQ 4 ; если счетчик достиг четырех, NN = 0 ; сбросить его XDW WD ; компилировать слово с накопленными командами LITS ; компилировать вслед за командами накопленные литералы WD = 0 ; сбросить в ноль "накопитель нибблов" ENDIF ENDM
; неразрывный код с литералом NIBBLIT MACRO N,dat ; размещение компилируемого ниббла в "накопителе нибблов" для последующей компиляции, когда их наберется 4 штуки WD = WD*16 + N NN = NN+1 ; счетчик нибблов IF NN EQ 4 ; если счетчик достиг четырех, LITERAL dat ; предкомпилировать литерал NN = 0 ; сбросить счетчик нибблов XDW WD ; компилировать слово с накопленными командами LITS ; компилировать вслед за командами накопленные литералы WD = 0 ; сбросить в ноль "накопитель нибблов" ELSE LITERAL dat ; предкомпилировать литерал ENDIF ENDM
; компиляция NOP-ов для выравнивания компилируемого кода на слово _compile_ MACRO ; компилировать нулевые нибблы, пока счетчик нибблов не обнулится IF NN GT 0 NIBBLE 0 ENDIF IF NN GT 0 NIBBLE 0 ENDIF IF NN GT 0 NIBBLE 0 ENDIF ENDM
; вспомогательное слово для компиляции адреса NEXTA MACRO addr A1 = ((addr-begin) / 2) XDW A1 ENDM ; --- теперь ассемблерные макрокоманды для процессора EQUINOX ------
_NOP MACRO NIBBLE 0 _compile_ ; за командой NOP следуют только NOP-ы ENDM
_RET MACRO NIBBLE 1 ENDM
_RET_ MACRO _RET _compile_ ENDM
_CALL MACRO addr a1 = ((addr-begin)/2) ; NIBBLE 2 ; LITERAL a1 NIBBLIT 2,a1 _compile_ ; команда CALL - последняя значащая в текущей четверке нибблов ENDM
_BRANDROP MACRO addr a1 = ((addr-begin)/2) _compile_ NIBBLIT 3,a1 NIBBLE 12 _compile_ ENDM
_JZ MACRO addr _BRANDROP addr ENDM
_IFNOT MACRO addr _LCONV _BRANDROP addr ENDM _IF MACRO addr _LCONV _BRANDROP addr ENDM
_BRAN MACRO addr a1 = ((addr-begin)/2) ; NIBBLE 3 ; LITERAL a1 NIBBLIT 3,a1 _compile_ ; команда BRANCH - последняя значащая в текущей четверке нибблов ENDM
_LIT MACRO data ; NIBBLE 4 ; LITERAL data NIBBLIT 4,data ENDM
_RAZIM MACRO NIBBLE 5 ENDM
_PRISW MACRO NIBBLE 6 ENDM
_STOP MACRO NIBBLE 7 ENDM
_toR MACRO NIBBLE 8 ENDM
_fromR MACRO NIBBLE 9 ENDM
; макрос для префиксной команды с увеличением глубины стека XDUP MACRO N IF NN EQ 3 NIBBLE 0 NIBBLE 10 NIBBLE N ELSE NIBBLE 10 NIBBLE N ENDIF ENDM
_DUP MACRO XDUP 0 ENDM _OVER MACRO XDUP 1 ENDM _ZERO MACRO XDUP 2 ENDM _MONE MACRO XDUP 3 ENDM
; макрос для префиксной команды с неизменной глубиной стека XSWAP MACRO N
IF NN EQ 3 NIBBLE 0 NIBBLE 11 NIBBLE N ELSE NIBBLE 11 NIBBLE N ENDIF ENDM
_SWAP MACRO XSWAP 0 ENDM _INC MACRO XSWAP 1 ENDM _DEC MACRO XSWAP 2 ENDM _NEG MACRO XSWAP 3 ENDM _INV MACRO XSWAP 4 ENDM _MUL MACRO XSWAP 5 ENDM _LCONV MACRO XSWAP 6 ENDM _BSWAP MACRO XSWAP 7 ENDM _LSHIFT MACRO XSWAP 8 ENDM _RSHIFT MACRO XSWAP 9 ENDM
; макрос для префиксной команды с уменьшением глубины стека XDROP MACRO N IF NN EQ 3 NIBBLE 0 NIBBLE 12 NIBBLE N ELSE NIBBLE 12 NIBBLE N ENDIF ENDM
_DROP MACRO XDROP 0 ENDM _NIP MACRO XDROP 1 ENDM _ADD MACRO XDROP 2 ENDM _SUB MACRO XDROP 3 ENDM _AND MACRO XDROP 4 ENDM _OR MACRO XDROP 5 ENDM _XOR MACRO XDROP 6 ENDM _NAND MACRO XDROP 7 ENDM _ADC MACRO XDROP 8 ENDM _SBC MACRO XDROP 9 ENDM
; резервные команды процессора
_NOP13 MACRO NIBBLE 13 ENDM
_NOP14 MACRO NIBBLE 14 ENDM
_NOP15 MACRO NIBBLE 15 ENDM
_CMP MACRO data _LIT data _XOR ENDM
_LIT@ MACRO addr _LIT addr _RAZIM ENDM
_LIT_PRISW MACRO addr _LIT addr _PRISW ENDM
_JMP MACRO addr _ZERO _IFNOT addr ENDM _RET_ MACRO _RET _compile_ ENDM _TRUE MACRO _MONE ENDM _FALSE MACRO _ZERO ENDM
A теперь маленький фокус:
Представленный ниже код есть не что иное, как ассемблер для Форт-процессора EQUINOX 16, использующий самый обычный "старинный" борландовский TASM версии 3.1
Спрашивать, почему TASM, а не FORTH - не нужно. Ибо такова селяви.
Чтобы написать программу для EQUINOX на TASM-e надо всего лишь включить данный код в начало файла с исходником и использовать описанные макросы (начинающиеся с символа подчеркивания) как форт-команды.
[code]; -------------------------------------- ; 28.03.2012 vers 1.02 ; макро-определения для форт-процессора EQUINOX 16 ; (c) 2012 WingLion ; для использования с турбоассемблером TASM v3.1 ; -------------------------------------- ; ; Справка: система команд процессора EQUINOX (март 2012 года) ; ; команда код описание ; NOP - 0 - нет операции - загрузка следующего командного слова ; RET - 1 - возврат из подпрограммы ; CALL - 2 L - вызов подпрограммы ; BRAN - 3 L - условный переход по нулю в стеке данных ; LIT - 4 L - загрузка литерала ; ! - 5 - стандартное фортовое "присвоить" ; @ - 6 - стандартное фортовое "разыменовать" ; STOP - 7 - остановить процесс исполнения (HALT) ; >R - 8 - переместить число со стека данных на стек возвратов ; R> - 9 - переместить число со стека возвратов на стек данных ; XDUP - А p - АЛУ операция с уменьшением глубины стека ; XSWAP B p - АЛУ операция с неизменной глубиной стека ; XDROP C p - АЛУ операьия с увеличением глубины стека ; NOP13 D - оперция не определена ; NOP14 E - оперция не определена ; NOP15 F - оперция не определена ; ; - L - требует литерала ; - p - префиксная команда
; --- вспомогательные макросы ---
; организация компиляции на виртуальном адресе addr
ORGS MACRO addr
NN = 0 ; -- сброс числа нибблов NL = 0 ; -- сброс числа литералов NMAX = 4 ; максимальное число нибблов в слове и литералов в команде WD = 0 ; "накопитель нибблов" - текущее слово для компиляции
A1 = (100h + addr*2) ; нулевой адрес в 100h
ORG A1 ; самый обыкнoвенный ORG
ENDM
; компиляция слова (при необходимости можно переставить байты)
XDW MACRO data
;B1 = data / 256 ; старший ;B2 = data - (B1*256) ; младший ; DB B1 ; DB B2
DW data
ENDM
; компиляция литералов - размещение литералов после командного слова
LITS MACRO IF NL GT 0 XDW L1 ENDIF IF NL GT 1 XDW L2 ENDIF IF NL GT 2 XDW L3 ENDIF IF NL GT 3 XDW L4 ENDIF NL = 0 ENDM
; предкомпиляция литералов - размещение литералов в переменных ; для последующей компиляции после командного слова
LITERAL MACRO addr IF NL EQ 0 L1 = addr ENDIF IF NL EQ 1 L2 = addr ENDIF IF NL EQ 2 L3 = addr ENDIF IF NL EQ 3 L4 = addr ENDIF NL = NL + 1 ENDM
; компиляция четырехбитной команды
NIBBLE MACRO N ; размещение компилируемого ниббла в "накопителе нибблов" для последующей компиляции, когда их наберется 4 штуки WD = WD*16 + N NN = NN+1 ; счетчик нибблов IF NN EQ 4 ; если счетчик достиг четырех, NN = 0 ; сбросить его XDW WD ; компилировать слово с накопленными командами LITS ; компилировать вслед за командами накопленные литералы WD = 0 ; сбросить в ноль "накопитель нибблов" ENDIF ENDM
; неразрывный код с литералом NIBBLIT MACRO N,dat ; размещение компилируемого ниббла в "накопителе нибблов" для последующей компиляции, когда их наберется 4 штуки WD = WD*16 + N NN = NN+1 ; счетчик нибблов IF NN EQ 4 ; если счетчик достиг четырех, LITERAL dat ; предкомпилировать литерал NN = 0 ; сбросить счетчик нибблов XDW WD ; компилировать слово с накопленными командами LITS ; компилировать вслед за командами накопленные литералы WD = 0 ; сбросить в ноль "накопитель нибблов" ELSE LITERAL dat ; предкомпилировать литерал ENDIF ENDM
; компиляция NOP-ов для выравнивания компилируемого кода на слово _compile_ MACRO ; компилировать нулевые нибблы, пока счетчик нибблов не обнулится IF NN GT 0 NIBBLE 0 ENDIF IF NN GT 0 NIBBLE 0 ENDIF IF NN GT 0 NIBBLE 0 ENDIF ENDM
; вспомогательное слово для компиляции адреса NEXTA MACRO addr A1 = ((addr-begin) / 2) XDW A1 ENDM ; --- теперь ассемблерные макрокоманды для процессора EQUINOX ------
_NOP MACRO NIBBLE 0 _compile_ ; за командой NOP следуют только NOP-ы ENDM
_RET MACRO NIBBLE 1 ENDM
_RET_ MACRO _RET _compile_ ENDM
_CALL MACRO addr a1 = ((addr-begin)/2) ; NIBBLE 2 ; LITERAL a1 NIBBLIT 2,a1 _compile_ ; команда CALL - последняя значащая в текущей четверке нибблов ENDM
_BRANDROP MACRO addr a1 = ((addr-begin)/2) _compile_ NIBBLIT 3,a1 NIBBLE 12 _compile_ ENDM
_JZ MACRO addr _BRANDROP addr ENDM
_IFNOT MACRO addr _LCONV _BRANDROP addr ENDM _IF MACRO addr _LCONV _BRANDROP addr ENDM
_BRAN MACRO addr a1 = ((addr-begin)/2) ; NIBBLE 3 ; LITERAL a1 NIBBLIT 3,a1 _compile_ ; команда BRANCH - последняя значащая в текущей четверке нибблов ENDM
_LIT MACRO data ; NIBBLE 4 ; LITERAL data NIBBLIT 4,data ENDM
_RAZIM MACRO NIBBLE 5 ENDM
_PRISW MACRO NIBBLE 6 ENDM
_STOP MACRO NIBBLE 7 ENDM
_toR MACRO NIBBLE 8 ENDM
_fromR MACRO NIBBLE 9 ENDM
; макрос для префиксной команды с увеличением глубины стека XDUP MACRO N IF NN EQ 3 NIBBLE 0 NIBBLE 10 NIBBLE N ELSE NIBBLE 10 NIBBLE N ENDIF ENDM
_DUP MACRO XDUP 0 ENDM _OVER MACRO XDUP 1 ENDM _ZERO MACRO XDUP 2 ENDM _MONE MACRO XDUP 3 ENDM
; макрос для префиксной команды с неизменной глубиной стека XSWAP MACRO N
IF NN EQ 3 NIBBLE 0 NIBBLE 11 NIBBLE N ELSE NIBBLE 11 NIBBLE N ENDIF ENDM
_SWAP MACRO XSWAP 0 ENDM _INC MACRO XSWAP 1 ENDM _DEC MACRO XSWAP 2 ENDM _NEG MACRO XSWAP 3 ENDM _INV MACRO XSWAP 4 ENDM _MUL MACRO XSWAP 5 ENDM _LCONV MACRO XSWAP 6 ENDM _BSWAP MACRO XSWAP 7 ENDM _LSHIFT MACRO XSWAP 8 ENDM _RSHIFT MACRO XSWAP 9 ENDM
; макрос для префиксной команды с уменьшением глубины стека XDROP MACRO N IF NN EQ 3 NIBBLE 0 NIBBLE 12 NIBBLE N ELSE NIBBLE 12 NIBBLE N ENDIF ENDM
_DROP MACRO XDROP 0 ENDM _NIP MACRO XDROP 1 ENDM _ADD MACRO XDROP 2 ENDM _SUB MACRO XDROP 3 ENDM _AND MACRO XDROP 4 ENDM _OR MACRO XDROP 5 ENDM _XOR MACRO XDROP 6 ENDM _NAND MACRO XDROP 7 ENDM _ADC MACRO XDROP 8 ENDM _SBC MACRO XDROP 9 ENDM
; резервные команды процессора
_NOP13 MACRO NIBBLE 13 ENDM
_NOP14 MACRO NIBBLE 14 ENDM
_NOP15 MACRO NIBBLE 15 ENDM
_CMP MACRO data _LIT data _XOR ENDM
_LIT@ MACRO addr _LIT addr _RAZIM ENDM
_LIT_PRISW MACRO addr _LIT addr _PRISW ENDM
_JMP MACRO addr _ZERO _IFNOT addr ENDM _RET_ MACRO _RET _compile_ ENDM _TRUE MACRO _MONE ENDM _FALSE MACRO _ZERO ENDM
[/code]
|
|
|
|
Добавлено: Пн мар 19, 2012 16:33 |
|
|
|
|