FORTH-ассемблер

Перейти вниз

FORTH-ассемблер

Сообщение автор Gudleifr в Ср Июн 28, 2017 12:43 pm

Эта штука относится к вещам, о которых говорят, либо: "Давно все уже сделано",- это, если никто не требует показать, либо: "И делать не стоит",- это, если просят. И такой подход действительно имеет глубокие корни в мышлении микро-фортеров.
***

Попробуем разобраться. Каково место FORTH в разработке ПО?
Тут опять повторю старый кусок - ТЕМА #30, АБЗАЦ #578:

0) Программирование нулевого уровня - ручной ввод команд одна за другой.
1) Командные файлы (скрипты) - несколько команд "упакованных в одну", возможно даже с какой-то примитивной логикой "если ошибка, то...".
2) "Программы с вводом".
3) FORTH.
4) BASIC.

Однако, как ни назови, несомненно одно: нам придется залезть внутрь нашей исходной машины. И начать писать не на исходном языке команд, а в машинных кодах И большая часть нашего BASIC-интерпретатора будет в этих кодах и написана. В случае же использования FORTH-метода "отскок в коды" будет совсем невелик - всего десяток основополагающих слов. Но, все равно, будет.

Т.е. FORTH-ассемблер - это тот самый "отскок в коды" и состоит он из трех кусков:

1) ПСЕВДОСЛОВА. Код, который нам придется засунуть внутрь FORTH, чтобы тот заработал. Очевидно, писать его придется еще не в FORTH (а, например, в debug.com). Это очень важный кусок кода, который самому FORTH почти "не виден". О нем поговорим (точнее, послушаем Мура, когда будем обсуждать писание FORTH-системы "с нуля"). Псевдословами их назовем, т.к. скоре всего они не будут оформлены в системе, как настоящие слова.

2) ВНУТРЕННИЕ КОДОВЫЕ СЛОВА. Код, который может понадобиться FORTH для более удобного объединения "команд в скрипты": всякие там расширенные средства работы со СТЕКОМ, СЛОВАРЕМ, ЗНАЧЕНИЕМ и ПОТОКОМ.

3) ВНЕШНИЕ КОДОВЫЕ СЛОВА. Код для написания новых "команд для скриптов". Что понадобится пользователю, мы не знаем, может, телескопом управлять, а, может, с распределенными базами данных работать... Значит, надо ему оставить лазейку для написания "чего угодно". (Кстати, эта возможность изначально была во всякого рода BASIC-ах и даже FoxBase+-ах и не является следствием особенности FORTH).

Прежде чем рассматривать отличие ВНУТРЕННИХ от ВНЕШНИХ, посмотрим, как их можно организовать.


Последний раз редактировалось: Gudleifr (Вт Янв 23, 2018 9:46 pm), всего редактировалось 7 раз(а)
avatar
Gudleifr
Admin

Сообщения : 932
Дата регистрации : 2017-03-29

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: FORTH-ассемблер

Сообщение автор Gudleifr в Ср Июн 28, 2017 12:43 pm

CHARLES H.MOORE PROGRAMMING A PROBLEM-ORIENTED-LANGUAGE
4. PROGRAMS THAT GROW / ПРОГРАММЫ, КОТОРЫЕ РАСТУТ
4.5. CODE ENTRIES / КОДОВЫЕ СТАТЬИ

Я объяснил, как компилировать инструкции для виртуального компьютера. А как быть с компиляцией для настоящего компьютера? Конечно, вы можете это сделать. Но, вероятно, не будете.

Работает Основной Принцип. Если вы добавляете код в вашу программу, вы добавляете максимальную мощность и гибкость. Вы можете все, что может компьютер. Это прекрасно, но вам это очень редко надо. И затраты растут. Для этого вам понадобится штук десять статей, плюс мнемоники инструкций. Кроме того, вы еще должны будете изобретать прикладной язык компиляции.

Мы написали программу поддержки языка. Если нужен новый код проще добавить его в программу и перекомпилировать. Конечно, вашей целью может быть написание приложения, компилирующего код. Или ваши пользователи хотят иметь код по своему вкусу. Только тогда Основной Принцип оправдает такое усложнение.

С другой стороны, если вы научитесь компилировать код, вы сможете создавать новые арифметические операторы, новые типы существительных, компилирующие слова. В Главе 9 я покажу, как вы можете использовать код с пользой, достигая максималной эфективности. Но, все это крайние меры.

Как вы можете генерировать код? Сначала вы нуждаетесь в статье, создающей кодовую статью. Главное свойство кодовых статей - хранение кода в поле параметров. Адрес, попадающий в ENTRY, должен быть получен определением (назовем его CODE) и показывать на начало куска кода. DP не подходит, т.к. должно быть еще зарезервировано место под заголовок статьи.

Нужна статья для сохранения числа по адресу DP. Мы использовали эту подпрограмму уже несколько раз, строя переменные и определения, но мы не оформляли ее в виде статьи. Я предлагаю слово "," хотя так мы уже называли слово печати числа. Все что оно делает, это кладет верхнее число со стека в поле параметров. Наши коды, ведь, тоже числа. Вы будете строить их на стеке и затем записывать. Такое слово окажется полезным не только для компиляции кода. Им будет удобно инициализировать самые разные данные.

Теперь вы можете понять мои давнишние опасения. Вы будете должны создать множество словарных статей, которые компилируют полезный код, но не вызываются напрямую. Например, RETURN: когда программа закончена, она должна перейти в цикл управления. Однако, где в памяти входная точка цикла управления? Так что вы должны будете создать статью для RETURN, чтобы она связалась при компиляции.

Аналогично, если вы создаете компилирующие слова, вы должны создавать и статьи для хранения кода, адрес которого будет передаваться ENTER. Благодаря этому, к вашим WORD и NUMBER сможет получить доступ кто угодно. Кроме того, надо будет определить статьи для используемых переменных: D и F для вывода; STATE и BASE. Проблема состоит в том, что вы делаете доступными извне внутренние точки программы. Вы, поэтому, должны обосновать их доступность их полезностью.

Вот и поговорили. Теперь о том, как строить инструкцию. Она состоит из нескольких частей - код операции, индекс, адрес, которые надо как-то скомбинировать. Это легко делать, но трудно спроектировать. Просто так копировать ассемблер не интересно. Это будет работа по созданию полноценного компилятора. Но все необходимые для вас инструменты уже есть - определения.

Вы можете без проблем написать определение, объединяющее (по "или") код операции и адрес и размещающее их. Если надо, вы можете преобразовывать абсолютные адреса в относительные или использовать страничную организацию. Вы можете все. Компилятор, он и есть компилятор - серьезная программа.

Мы обсуждали условные и циклические конструкции виртуального компьютера. Подобные методы можно использовать и здесь. На самом деле, я впервые применил стековое разрешение переходов для написания кодов моего реального компьютера. Когда превращал ассемблер в компилятор. Помните Основной Принцип.

Компилятор позволит определять новые виды существительных. Т.е. строить новые определяющие слова. Рассмотрим пример описанного выше. Напишем слово, умножающее верхнее число стека на константу.

Как обычно, требуется совместно использовать несколько специальных слов. В этом случае - ENTER и ;CODE . Вот так:

: UNIT ENTER , ;CODE 1 V LDA , SP MPY , SP STA , NEXT ,
2.54 UNIT IN
4. IN

В первой строке определяется слово UNIT (т.е. единица измерения). В cледующей строке оно используется, чтобы определить слово IN (в дюймах). В последней строке при помощи IN в сантиметры переводится 4 дюйма. Эквивалентное определение IN

: IN 2.54 * ;

оно, конечно же проще. Но, зато, при помощи UNIT вы можете эффективно определить много подобных слов.

Первое из новых слов - ENTER. Оно вызывает подпрограмму ENTRY как всякое определяющее слово, но пишет 0 в поле адреса. Смотрим на определение UNIT. Слово ENTER обязательно. Оно производит псевдо-инструкцию двойной длины; псевдо-статью и 0. Во время выполнения псевдо-статья вызовет ENTRY (чтобы построить новую словарную статью), передавая ему 0 из второй половины псевдо-инструкции. Слово ;CODE - комбинация слов ";" и CODE. Оно заканчивает определение UNIT и сохраняет DP в поле адреса, установленное ENTER. Т.о. код, который следует за ;CODE, будет выполняться для всех статей, созданных UNIT. ;CODE знает, куда сохранять DP потому, что ENTER обязательно первое слово в подобных определениях и ;CODE знает, какое определение оно заканчивает.

Ограничение на расположение ENTER в начале определения незначительно. "," в UNIT нужна для размнщения константы. Другие существительные могли бы нуждаться в более сложном коде для формирования поля параметров.

Вы видите код после ;CODE - инструкции и адреса, обращающиеся в т.ч. к константе, размещенной ",". Я не хочу объяснять язык своего ассемблирующего компилятора, т.к. для вашей машины будет нужен другой.

Еще одна полезная идея. Вы можете определить новый вид констант - инструкции. Когда они исполняются, снимают со стека адрес, комбинируют его с инструкцией, хранящейся в поле параметров, и размещают результат. Таких инструкций понадобится много. И статей, ими созданных, тоже будет много.

Боюсь, пример здесь не поможет. Если вы не поняли, как делать кодовые слова, забудьте. Приложение с кодовыми словами будет слишком машинно-зависимым. Обычные определения гораздо удобнее. Код нужен только для доступа к специфическим возможностям вашего компьютера.
avatar
Gudleifr
Admin

Сообщения : 932
Дата регистрации : 2017-03-29

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: FORTH-ассемблер

Сообщение автор Gudleifr в Ср Июн 28, 2017 12:44 pm

Таким образом, мы видим, что FORTH-ассемблер состоит всего из двух деталей - "запятой" и некоего способа передавать управление на то, что при помощи этой "запятой" нафигачили.

Т.е. все дальнейшее совершенствование FORTH-ассемблеров сводится к приданию "запятой" большьшей мощности и удобства. Научить ее записывать не только откомпилированные вручную машинные коды, но и красивые слова на высокоуровневом макро-языке.

Тут, как раз всплывает различие между ВНУТРЕННИМИ и ВНЕШНИМИ КОДОВЫМИ СЛОВАМИ. Для программирования первых достаточно очень ограниченного набора машинных комманд (как и для написания обычного компилятора). Что порождает у микрофортеров желание создать FORTH-ассеблер для этого набора, придумав десяток красивых имен для "нужного" и забыв про "ненужное". Настоящие программисты сказали бы, что они пытаются придумать набор макросов на все случаи жизни.

Для ВНЕШНИХ КОДОВЫХ слов, конечно хочется иметь возможность использовать любые машинные коды без ограничений (даже, на всякий случай, те, использование куторых обрушит FORTH- или Операционную Систему).

Эти два взаимоисключающих подхода и порождают не дают фортерам понять, что же такое FORTH-ассемблер? Не проще ли иметь два разных?

Но, позвольте, есть же универсальное решение!
avatar
Gudleifr
Admin

Сообщения : 932
Дата регистрации : 2017-03-29

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: FORTH-ассемблер

Сообщение автор Gudleifr в Ср Июн 28, 2017 12:46 pm

С.Н.БАРАНОВ И Н.Р.НОЗДРУНОВ ЯЗЫК ФОРТ И ЕГО РЕАЛИЗАЦИИ
3.ПРИМЕРЫ ПРОГРАММНЫХ РАЗРАБОТОК
11.РЕАЛИЗАЦИЯ ВСТРОЕННОГО АССЕМБЛЕРА

Приводимый ниже текст является законченной реализацией встроенного структурного ассемблера для форт-систем на базе микропроцессора К580. В оттранслированном виде он занимает около 1300 байт и является типичным для 8-разрядных микропроцессоров. Для 16- или 32-разрядных процессоров в силу их большей сложности объем текста больше. Но даже в этом случае объем исходного текста и скомпилированного кода существенно меньше, чем для традиционных ассемблеров.

( FORTH-83 АССЕМБЛЕР ДЛЯ К580 ТЕМАШКИНО 1985 )
VOCABULARY ASSEMBLER
ASSEMBLER DEFINITIONS

( МАШИННЫЕ КОМАНДЫ )
DECIMAL : 8* 2* 2* 2* ;
4 CONSTANT H 5 CONSTANT L 7 CONSTANT A 6 CONSTANT PSW
2 CONSTANT D 3 CONSTANT E 0 CONSTANT B 1 CONSTANT C
6 CONSTANT M 6 CONSTANT SP
: 1MI ( ---> ) CREATE C, DOES> C@ C, ;
: 2MI ( ---> ) CREATE C, DOES> C@ + C, ;
: 3MI ( ---> ) CREATE C, DOES> C@ SWAP 8* + C, ;
: 4MI ( ---> ) CREATE C, DOES> C@ C, C, ;
: 5MI ( ---> ) CREATE C, DOES> C@ C, , ;

HEX
00 1MI NOP 76 1MI HLT F3 1MI DI FB 1MI EI
07 1MI RLC 0F 1MI RRC 17 1MI RAL 1F 1MI RAR
E9 1MI PCHL F9 1MI SPHL E3 1MI XTHL EB 1MI XCHG
27 1MI DAA 2F 1MI CMA 37 1MI STC 3F 1MI CMC
80 2MI ADD 88 2MI ADC 90 2MI SUB 98 2MI SBB
A0 2MI ANA A8 2MI XRA B0 2MI CRA B8 2MI CMP
09 3MI DAD C1 3MI POP C5 3MI PUSH 02 3MI STAX
0A 3MI LDAX 04 3MI INR 05 3MI DCR 03 3MI INX
0B 3MI DCX C7 3MI RST D3 4MI OUT DB 4MI IN
C6 4MI ADI CE 4MI ACI D6 4MI SU1 DE 4MI SBI
E6 4MI ANI EE 4MI XRI F6 4MI ORI FE 4MI CPI
22 5MI SHLD 2A 5MI LHLD 32 5MI STA 3A 5MI LDA
C4 5MI CNZ CC 5MI CZ D4 5MI CNC DC 5MI CC
E4 5MI CPO EC 5MI CPE F4 5MI CP FC 5MI CM
CD 5MI CALL C9 1MI RET C3 5MI JMP
C0 1MI RNZ C8 1MI RZ D0 1MI RNC DB 1MI RC
E0 1MI RPO E8 1MI RPE F0 1MI RP F8 1MI RM
C2 5MI JNZ CA 5MI JZ D2 5MI JNC DA 5MI JC
E2 5MI JPO EA 5MI JPE F2 5MI JP FA 5MI JM

: MOV SWAP 8* 40 + + C, ;
: MVI SWAP 8* 6 + C, C, ;
: LXI SWAP 8* 1 + C, , ;

( КОДЫ УСЛОВИЙ ДЛЯ СТРУКТУР УПРАВЛЕНИЯ )
C2 CONSTANT 0= D2 CONSTANT CS
E2 CONSTANT PE F2 CONSTANT 0<

( СТРУКТУРЫ УПРАВЛЕНИЯ )
DECIMAL
: NOT ( N:КОД УСЛОВИЯ ---> N1) 8 + ;
: THEN ( АДР,2 ---> ) 2 ?PAIRS HERE SWAP ! ;
: IF ( КОД ---> АДР,2 ) C, HERE 0 , 2 ;
: ELSE ( АДР,2 ---> АДР1,2) 2 ?PAIRS C3 IF ROT SWAP THEN 2 ;
: BEGIN ( ---> АДР,1 ) HERE 1 ;
: UNTIL ( АДР,1,КОД --->) SWAP 1 ?PAIRS С, , ;
: AGAIN ( АДР,1 --->) 1 ?PAIRS C3 C, , ;
: WHILE ( АДР,1,КОД ---> АДР,1,АДР1,4) IF 2 + ;
: REPEAT ( АДР,1,АДР1,4 --->) >R >R AGAIN R> R> 2- THEN ;

( РАБОТА С МЕТКАМИ )
10 CONSTANT LBLMAX ( МАКСИМАЛЬНОЕ ЧИСЛО ЛОКАЛЬНЫХ МЕТОК)
VARIABLE LTABLE LBLMAX 1+ 2* ALLOT
10 CONSTANT FRMAX ( МАКСИМАЛЬНОЕ ЧИСЛО ССЫЛОК ВПЕРЕД)
VARIABLE FRTABLE FRMAX 2* 2* ALLOT
: FRCHK ( ---> ПРОВЕРКА НЕРАЗРЕШЕННЫХ ССЫЛОК ВПЕРЕД )
FRMAX 0 DO I 2* 2* FRTABLE + @
ABORT" НЕРАЗРЕШЕННАЯ ССЫЛКА ВПЕРЕД"
LOOP ;
: FRCLR ( ---> ИНИЦИАЛИЗАЦИЯ ТАБЛИЦЫ ССЫЛОК ВПЕРЕД )
FRTABLE FRMAX 2* 2* ERASE
LTABLE LBLMAX 1+ 2* ERASE ;
: FRRES ( N:МЕТКА ---> РАЗРЕШЕНИЕ ССЫЛОК ВПЕРЕД )
FRMAX 0 DO I 2* 2* FRTABLE + 2DUP @ =
IF HERE OVER 2+ @ +! 0!
ELSE DROP THEN
LOOP ;
: FRADD ( N:МЕТКА ---> ДОБАВЛЕНИЕ ССЫЛКИ ВПЕРЕД В ТАБЛИЦУ )
FRMAX 1+ 0
DO FRMAX I = ABORT" СЛИШКОМ МНОГО ССЫЛОК ВПЕРЕД"
I 2* 2* FRTABLE + DUP @ 0=
IF 2DUP ! HERE 1+ SWAP 2+ ! LEAVE ELSE DROP THEN
LOOP ;

( ОПРЕДЕЛЯЮЩИЕ ВХОЖДЕНИЯ МЕТОК )
: !LT CREATE , DOES> @ FRRES HERE SWAP 2* LTABLE + ! ;
( ИСПОЛЬЗУЮЩИЕ ВХОЖДЕНИЯ МЕТОК )
: @LT CREATE , DOES> @ DUP 2*
LTABLE + @ SWAP OVER 0=
IF FRADD THEN DROP ;
1 !LT 1#: 2 !LT 2#: 3 !LT 3#: 4 !LT 4#! 5 !LT 5#:
6 !LT 6#: 7 !LT 7#: 8 !LT 8#: 9 !LT 9#! 10 !LT 10#:
1 @LT 1# 2 @LT 2# 3 @LT 3# 4 @LT 4# 5 @LT 5#
6 @LT 6# 7 @LT 7# 8 @LT 8# 9 @LT 9# 10 @LT 10#

( ПЕРЕКЛКЮЧЕНИЕ В АССЕМБЛЕР )
FORTH DEFINITIONS '
: BEG-ASM [ ASSEMBLER ] FRCLR [ FORTH ] ASSEMBLER
!CSP ;
: END-ASM [ ASSEMBLER ] FRCHK [ FORTH ] ?CSP ...

В приведенном тексте можно выделить четыре группы определений: машинные команды, структуры управления, метки и стандартные слова для создания определении в машинном коде. Помимо них данный текст определяет ряд вспомогательных слов.

Машинные команды на языке ассемблера записываются в обратной польской форме, принятой для языка Форт: <операнды> <операция>, где <операнды> - слова, вычисляющие на стеке размещения операндов данной машинной команды, а <операция> - ее мнемоника. Для обозначения регистров микропроцессора К580 зарезервированы слова А В С D E H L , для задания регистровых пар используются слова В D H SP PSW , для косвенной адресации через регистровую пару HL - слово М . При исполнении слов, обозначающих регистры, регистровые пары и косвенную адресацию, на стеке оставляются значения, соответствующие принятым в системе команд К580 обозначениям для регистров и регистровых пар:

ABCDEHLMSPPSW
7012345666

При исполнении мнемоники машинной команды на вершину словаря компилируется соответствующая машинная инструкция. Размещения операндов при этом снимаются со стека. Порядок вычисления операндов машинной команды соответствуют порядку написания операндов на обычном языке ассемблера.

Ниже приведены для сравнения записи машинных команд на обычном языке ассемблера и на языке ассемблера данной форт-системы:

HLTHLT
DAD SPSP DAD
PUSH PSWPSW PUSH
CMP CC CMP
MOV A,MA M MVI
MVI B,2B 2 MVI
LXI 0,120+8D 120 8 + LXI
CALL 5002HHEX 5002 CALL DECIMAL

Для определения мнемоник используются определяющие слова, соответствующие форматам машинных команд ( 1MI , ..., 5MI ). Все они имеют одинаковую создающую часть, которая компилирует в поле параметров статьи для мнемоники однобайтный код маски для кода данной команды, который снимается со стека. Исполняющая часть определений, используя маску и размещения операндов, которые она снимает со стека, компилирует двоичный код, соответствующий данной команде. Так, например, через елово 1MI определяются машинные команды, не имеющие операндов. При исполнении мнемоники такой команды на вершину словаря компилируется однобайтный код операции. Слово 3MI определяет мнемоники команд, имеющих один операнд - номер регистра. Этот номер занимает разряды со 2 по 4 в однобайтном коде команды. Поэтому исполняющая часть сдвигает свой операнд - номер регистра - влево на 3 разряда исполнением слова 8* и добавляет к нему маску команды. Получившийся однобайтный код компилируется на вершину словаря. Три команды - MOV, MVI и LXI - не подходят под описанные общие форматы, поэтому они определяются непосредственно через двоеточие.

Структурные операторы встроенного ассемблера позволяют программировать разветвления и циклы без явно заданных команд перехода на метку. Их синтаксис аналогичен синтаксису соответствующих операторов языка Форт.

Условный оператор в полной или сокращенной форме записывается следующим образом:

<КОД-УСЛОВИЯ> IF <ЧАСТЬ-ТО> ELSE <ЧАСТЬ-ИНАЧЕ> THEN
<КОД-УСЛОВИЯ> IF <ЧАСТЬ-ТО> THEN

Часть "то" выполняется, только если в разрядах PSW установлен заданный "код условия", в противном случае выполняется часть "иначе", если она есть.

Циклы могут быть записаны в одной из трех форм:

BEGIN <ТЕЛО-ЦИКЛА> AGAIN
BEGIN <ТЕЛО-ЦИКЛА> <КОД-УСЛОВИЯ> UNTIL
BEGIN <ТЕЛО-1> <КОД-УСЛОВИЯ> WHILE <ТЕЛО-2> REPEAT

Цикл BEGIN-AGAIN является бесконечным, BEGIN-UNTIL прекращает выполнение при к указанном коде условия, в цикле BEGIN-WHILE-REPEAT, наоборот, указанный код условия задает продолжение цикла.
Для указания кода условия в ассемблере используются следующие слова: 0= - установлен флаг Z , 0< - флаг S , CS - флаг C , PE - флаг P . Для инвертирования кода условия используется слово NOT.

Структурные операторы компилируют на своем месте команды безусловных и условных переходов с указанным условием.

Для работы с явно задаваемыми метками в ассемблер включены слова вида 1#: 2#: ... 10#: и 1# 2# ... 10# . Слова первой группы задают определение метки, слова второй - использование. Метки имеют строго локальный характер, т.е. эти слова можно использовать только внутри определений через CODE и между словами ;CODE и END-CODE. Наряду с метками допускается использование ассемблерных структур управления.

Локальные метки рекомендуется использовать только в трехбайтных командах типа JMP , CALL , LXI . Уже определенные локальные метки могут участвовать в арифметических и стековых операциях; использующие вхождения меток, определяющие вхождения которых вводятся позднее (ссылки вперед), могут участвовать только в операциях, сводящихся к добавлению к ним числа со знаком.

Для реализации работы с метками ассемблер имеет таблицу меток LTABLE и таблицу ссылок вперед FRTABLE. Их размер определяет максимальное число разных меток и ссылок вперед в пределах одного определения в машинном коде (от слова CODE или ;CODE до слова END-CODE ). Для каждой возможной метки соответствующий элемент таблицы LTABLE содержит нуль, если метка еще не определена, или адрес, который является ее значением, если метка уже определена. Входом в эту таблицу служит номер метки. В таблице FRTABLE для каждой ссылки вперед хранятся два значения: номер метки и адрес в словаре, по которому нужно вписать ее значение. По этому адресу скомпилировано значение смещения, которое нужно добавить как число со знаком к значению данной метки.

Слова для использующих вхождений меток определяются через @LT, например 1 @LT 1# . Исполнение определенного таким образом слова 1#, обозначающего метку номер 1, состоит в обращении к таблице LTABLE по индексу 1. Если там стоит нуль, т. е. метка номер 1 еще не определена, то этот нуль выдается на стек в качестве смещения от значения метки, которое определится позднее. Одновременно в таблицу FRTABLE заносится запись о данной ссылке вперед. В качестве адреса, куда нужно будет впоследствии вписать значение метки, берется HERE 1+ . Здесь используется тот факт, что в микропроцессоре К580 операнд-адрес занимает 2 байта, следующие за однобайтным кодом операции.

Слова для определения меток определяются через слово !LT , например 1 !LT 1#: . Исполнение определенного таким образом слова 1#: определяет метку номер 1 как текущий адрес вершины словаря HERE . Его действие состоит в том, что выполняется просмотр таблицы FRTABLE с разрешением всех накопившихся ссылок на данную метку, после чего запись о данной метке заносится в таблицу LTABLE .

Последнюю группу определений составляют слова для доступа к встроенному ассемблеру при компиляции машинного кода. Помимо стандартных форт-слов CODE , ;CODE и END-CODE здесь определяются слова LABEL и NEXT; . Первое используется для создания именованных подпрограмм, к которым можно обращаться из машинного кода. Второе является сокращением для часто встречающегося окончания ассемблерных определений: NEXT JMP END-CODE . В качестве примера приведем определение слова >< , которое меняет местами байты в переданном на стеке двухбайтном значении:

CODE >< ( N1 ---> N2) H POP
A L MOV L H MOV H A MOV H PUSH NEXT;

Приведенная реализация встроенного ассемблера может быть усовершенствована по нескольким направлениям. Прежде всего, увеличив константы LBLMAX и FRMAX и добавив новые определения для слов, обозначающих метки, можно увеличить количество разных меток и ссылок вперед, которые разрешается использовать в ассемблерном определении. Далее можно ввести контроль правильности операндов, включив соответствующие проверки в исполняющую часть определяющих слов для мнемоник команд. Для проверки числа элементов на стеке обычно используется глобальная ячейка CSP и слово !CSP , которое засылает в нее текущий адрес вершины стека. Интересным расширением является возможность введения макрокоманд. Макрокоманды без локальных меток можно определять обычным образом через двоеточие:

INRN ( R:РЕГИСТР,H:ЧИСЛО РАЗ ---> )
[ ABSEMBLER ] 0 DO DUP INR LOOP DROP ;

При исполнении текста А 3 INRN будут скомпилированы три команды А INR. Если же макрорасширение должно порождать обращения к адресам через локальные метки, то потребуется более основательное расширение ассемблера.


Последний раз редактировалось: Gudleifr (Вт Янв 23, 2018 9:53 pm), всего редактировалось 1 раз(а)
avatar
Gudleifr
Admin

Сообщения : 932
Дата регистрации : 2017-03-29

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: FORTH-ассемблер

Сообщение автор Gudleifr в Ср Июн 28, 2017 12:48 pm

Т.е. практически все команды легко задаются в паре десятков строчек при помощи умных вариантов "запятой" - 1MI ... 5MI . Причем, весь их "ум" состоит в способности писать (компилировать) не одно число, а сразу несколько, в нужном формате. Написав эти "комиляторы" можно сразу, как предложено, добавлять ассемблеру уровень (т.е писать макросы).

Единственная сложность - надо знать эти самые машинные коды. Но, если мы честно написали свой FORTH со всеми его ПСЕВДОСЛОВАМИ, то, видимо, мы их знаем.

И, вот, на этой радостной ноте... "Пардон, кого вы дурите! Для моего процессора это не подходит!"
...

Действительно, для процессора, чуть более сложного, чем 8080 никаких 1MI... не хватит.
Попробуем посмотреть (16- и 32- разрядный FORTH-ассемблер для Intel-x86)...

\ Assembler. Compiler's words.
( Нотация: 1/2 - число байт
D/X - наличие бит dst/src/wrd
M/X - наличе довеска вместо поля reg)
: 1XX ( op->) <BUILDS C, DOES> ( ->) @ C, ;
: 1DX ( op->) <BUILDS C, DOES> ( dsw->) @ + C, ;
: 1XM ( op,reg->) <BUILDS C, C, DOES> ( ->reg) DUP 1+ @ C, C@ ;
: 1DM ( op,reg->) <BUILDS C, C, DOES> ( dsw->reg)
DUP 1+ @ ROT + C, C@ ;
: 1SR ( op->) <BUILDS C, DOES> ( sr->) @ SWAP 3 << + C, ;
: 2XX ( op->) <BUILDS , DOES> ( ->) @ , ;
: 2DX ( op->) <BUILDS , DOES> ( dst/src/wrd->)
@ SWAP 8 << + , ;
: 2XM ( op,reg->) <BUILDS C, , DOES> ( ->reg) DUP 1+ @ , C@ ;
: 2DM ( op,reg->) <BUILDS C, , DOES> ( dsw->reg)
DUP 1+ @ ROT 8 << + , C@ ;

(Кто не помнит, <BULDS ... DOES> это то же CREATE ... DOES> , только для FORTH с кривой реализацией CREATE).

Действительно, в x86 чуть более чем дофига разных команд. Деление на код и данные очень сильно зависит от формата команд. Есть коды, которые что-то втюхивают в поле данных, есть данные, дописывающиеся в конец кода...
1. Много префиксов (для модификации команд или тех команд, код которых не влезает в один байт). К счастью, префиксы простые, в их код не надо ничего вписывать (iXX).
2. Код большинства команд имеет в конце пару-другую бит, которые зависят от данных (iDX, 1SR).
3. За кодом команды следует байт (а в 32-битовом режиме, возможно и пара) управления данными. Если команда одноместная, сюда втюхивается непоместившийся в основные байты кусочек кода (iDM).
4. Размер, собственно, данных может быть самым разным, в зависимости от префиксов, кода и байтов управления данными.

\ Assembler. 8088. Команды без параметров.
\ 1XX-префиксы. ->
26 1XX ES: 2E 1XX CS: 36 1XX SS: 3E 1XX DS:
0F2 1XX REPNZ, 0F3 1XX REPZ,
\ 1XX-без-параметров. ->
27 1XX DAA, 2F 1XX DAS, 37 1XX AAA, 3F 1XX AAS,
90 1XX NOP, 98 1XX CBW, 99 1XX CWD, 9B 1XX WAIT,
9C 1XX PUSHF, 9D 1XX POPF, 9E 1XX SAHF, 9F 1XX LAHF,
0C3 1XX RET, 0CB 1XX RETFAR, 0CC 1XX INT3, 0CE 1XX INTO,
0CF 1XX IRET, 0D7 1XX XLAT, 0F0 1XX LOCK, 0F4 1XX HLT,
0F4 1XX HLT, 0F5 1XX CMC, 0F8 1XX CLC, 0F9 1XX STC,
0FA 1XX CLI, 0FB 1XX STI, 0FC 1XX CLD, 0FD 1XX STD,
\ 2XX-команды для коррекции результатов. ->
0AD4 2XX AAM, 0AD5 2XX AAD,

Это самое любимое место всех ассемблерописателей - просто коды, без какой-либо модификации.
avatar
Gudleifr
Admin

Сообщения : 932
Дата регистрации : 2017-03-29

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: FORTH-ассемблер

Сообщение автор Gudleifr в Ср Июн 28, 2017 12:49 pm

\ Assembler. 8088. Простые команды.
\ 1XX-ассорти. ->
8D 1XX LEA, ( rw,m) 8F 1XX POPM, ( mw)
9A 1XX CALLFAR, ( cd) 0C2 1XX RETD, ( dw)
0C4 1XX LES, ( rw,ed) 0C5 1XX LDS, ( rw,ed)
0CA 1XX RETFARD, ( dw) 0CD 1XX INT, ( db)
0E0 1XX LOOPNE, ( cb) 0E1 1XX LOOPE, ( cb)
0E2 1XX LOOP, ( cb) 0E3 1XX JCXZ, ( cb)
0E8 1XX CALL, ( cw) 0E9 1XX JMP, ( cw)
0EA 1XX JMPFAR, ( cd) 0EB 1XX JMPSHORT, ( cb)
\ Безпараметровые команды для регистров. (s)reg->
06 1SR PUSHSR, 07 1SR POPSR, 40 1DX INCR, 48 1DX DECR,
50 1DX PUSHR, 58 1DX POPR, 90 1DX XCHGA,
\ 1DX-классические команды. dst/wrd-> r,e /кроме MOV/.
0 1DX ADD, 8 1DX OR, 10 1DX ADC, 18 1DX SBB,
20 1DX AND, 28 1DX SUB, 30 1DX XOR, 38 1DX CMP,

\ Assembler. 8088. Константные команды.
\ 1DX-операции с аккумулятором. wrd-> d
4 1DX ADDA, 0C 1DX ORA, 14 1DX ADCA, 1C 1DX SBBA,
24 1DX ANDA, 2C 1DX SUBA, 34 1DX XORA, 3C 1DX CMPA,
0A8 1DX TESTA,
\ 1DX-умножение на константу. src-> rw,ew,d
69 1DX IMULD,
\ 1DM-команды Immed. src/wrd->reg e,d
80 0 1DM ADDD, 80 1 1DM ORD, 80 2 1DM ADCD,
80 3 1DM SBBD, 80 4 1DM ANDD, 80 5 1DM SUBD,
80 6 1DM XORD, 80 7 1DM CMPD, 0F6 0 1DM TESTD, ( без src)
\ MOV Immed.
0B0 1DX MOVRDB, ( reg-> db) 0B8 1DX MOVRDW, ( reg-> dw)
0C6 0 1DM MOVED, ( wrd->000 e,d)
\ IN/OUT Immed. ( wrd-> db)
0E4 1DX IN, 0E6 1DX OUT,

\ Assembler. 8088. Основные 1DM-команды.
\ 1DM-сдвиги. wrd->reg e
0D0 0 1DM ROL1, 0D0 1 1DM ROR1, 0D0 2 1DM RCL1, 0D0 3 1DM RCR1,
0D0 4 1DM SHL1, 0D0 5 1DM SHR1, 0D0 7 1DM SAR1,
0D2 0 1DM ROLC, 0D2 1 1DM RORC, 0D2 2 1DM RCLC, 0D2 3 1DM RCRC,
0D2 4 1DM SHLC, 0D2 5 1DM SHRC, 0D2 7 1DM SARC,
\ 1DM-унарные команды. wrd->reg e
0F6 2 1DM NOT, 0F6 3 1DM NEG, 0F6 4 1DM MUL,
0F6 5 1DM IMUL, 0F6 6 1DM DIV, 0F6 7 1DM IDIV,
0FE 0 1DM INC, 0FE 1 1DM DEC,
0FF 6 1XM PUSHE, ( ->110 ew)
\ 1XM-переходы. ->reg e
0FF 2 1XM CALLEW, 0FF 3 1XM CALLED, 0FF 4 1XM JMPEW,
0FF 5 1XM JMPED,

\ Assembler. 8088. Прочие команды.
\ 1DX-остальные случаи MOV.
88 1DX MOV, ( dst/wrd-> r,e) 8C 1DX MOVSR, ( dst-> sr,ew)
0A0 1DX MOVA, ( dst/wrd-> m)
\ 1DX-симметричные. wrd-> r,e
84 1DX TEST, 86 1DX XCHG,
\ 1DX-строковые операции. wrd->
0A4 1DX MOVS, 0A6 1DX CMPS, 0AA 1DX STOS, 0AC 1DX LODS,
0AE 1DX SCAS,
\ 1DX-условные переходы. cond-> cb 10 70 1DX J,
\ IDX-работа с портом DX. wrd->
0EC 1DX INDX, 0EE 1DX OUTDX,

И где это ваше изящество FORTH-ассемблера? Понятно, что постоянно помнить это невозможно, так что, разницу между писанием на языке ассемблере и тупо вбиванием кода команд можно почувствовать только постоянно этим занимаясь.
avatar
Gudleifr
Admin

Сообщения : 932
Дата регистрации : 2017-03-29

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: FORTH-ассемблер

Сообщение автор Gudleifr в Ср Июн 28, 2017 12:50 pm

Нет, это не все, переходим к данным

Историческая бумажка - мой первый опыт ксерокопирования. Документация по TURBO-чему-то.



\ Assembler. 8088. Операнды-константы.
\ Регистры. ->reg
0 CONSTANT A 1 CONSTANT C 2 CONSTANT D 3 CONSTANT B
4 CONSTANT AH 5 CONSTANT CH 6 CONSTANT DH 7 CONSTANT BH
4 CONSTANT SP 5 CONSTANT BP 6 CONSTANT SI 7 CONSTANT DI
0 CONSTANT ES 1 CONSTANT CS 2 CONSTANT SS 3 CONSTANT DS
\ ->dst/src/wrd
0 CONSTANT /BO 1 CONSTANT /WO 2 CONSTANT /DB 2 CONSTANT /SO
3 CONSTANT /DW 3 CONSTANT /SW
\ ->cond
0 CONSTANT ?OV 1 CONSTANT ?NV 2 CONSTANT ?CY 3 CONSTANT ?NC
14 CONSTANT ?ZR 5 CONSTANT ?NZ 6 CONSTANT ?CY|ZR
7 CONSTANT ?NC&NZ 8 CONSTANT ?NG 9 CONSTANT ?PL 0A CONSTANT ?PE
0B CONSTANT ?PO 0C CONSTANT ?NG#OV 0D CONSTANT ?NG=0V
0E CONSTANT ?ZR|NG#OV 0F CONSTANT ?NZ&NG=OV

\ Assembler. 8088. Образование mod.reg.RM.
: /BA 8 OR ; : /WA 10 OR ; ( reg->mod.reg)
: [RG] ( reg1,reg2->) SWAP 3 << OR 0C0 OR C, ; ( 11.reg1.reg2,)
\ mod.reg-> mod.reg.RM, Нотация: B-bx P-bp S-si D-di
0 1SR [BS] 1 1SR [BD] 2 1SR [PS] 3 1SR [PD] 4 1SR [S]
5 1SR [D] 6 1SR [10] ( при mod=00) 6 1SR [P] 7 1SR [B]

Наученный горьким опытом, я не стал придумывать имена для комбинаций данных (все эти квадратные скобочки, запятые  и WORD PTR) и тупо вбиваю управляющие поля руками. Окупается. Где-то после третьей команде, я вспоминаю систему (т.е. систему адресации данных) и начинаю вбивать на автомате.

Конечно, наопределять всяких разных синтаксисов операндов на основе моих "кирпичиков" - не проблема.

И, да, до 32-разрядной адресации мы еще не дошли.


Последний раз редактировалось: Gudleifr (Вт Янв 23, 2018 9:54 pm), всего редактировалось 3 раз(а)
avatar
Gudleifr
Admin

Сообщения : 932
Дата регистрации : 2017-03-29

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: FORTH-ассемблер

Сообщение автор Gudleifr в Ср Июн 28, 2017 12:50 pm

Новые процессоры - новые команды

\ Assembler. 80286. Команды защищенного режима.
\ 0F00 и 0F01 2XМ-команды ->reg ew
0F 0 2XM SLDT, 0F 1 2XM STR, 0F 2 2XM LLDT,
0F 3 2XM LTR, 0F 4 2XM VERR, 0F 5 2XM VERW,
10F 4 2XM SMSW, 10F 6 2XM LMSW,
\ 2XМ-команды ->reg ew /только память/
10F 0 2XM SGDT, 10F 1 2XM SIDT, 10F 0 2XM LGDT,
10F 3 2XM LIDT,
\ 0F 2XX-команды. ->
20F 2XX LAR, 30F 2XX LSL, ( rw,ew)
60F 2XX CLTS,
\ 1XX-проверка RPL. -> rw,ew
63 1XX ARPL,

\ Assembler. 80286. Прочие новые команды.
\ Работа со стеком.
60 1XX PUSHA, 61 1XX POPA,
80 1DX PUSHD, ( src-> d)
\ 1XX-проверка смещения. -> rw,ew /только память/
62 1XX BOUND,
\ 1DX-строковый ввод-вывод. w->
6C 1DX INS, 6E 1DX OUTS,
\ 1DM-сдвиги на константу. wrd->reg e,db
0C0 0 1DM ROLD, 0C0 1 1DM RORD, 0C0 2 1DM RCLD, 0C0 3 1DM RCRD,
0C0 4 1DM SHLD, 0C0 5 1DM SHRD, 0C0 7 1DM SARD,
\ 1XX-Pascal-процедуры. ->
0C8 1XX ENTER, ( dw,db)
0C9 1XX LEAVE,

В 80386:

\ Assembler. 80386. Новые команды.
\ Условные команды.
800F 2DX JNEAR, ( cond-> cw) 900F 0 2DM SET, ( cond->000 eb)
\ Проверка бита.
0A30F 2XX BT, 0AB0F 2XX BTS, ( -> rw,ew)
0B30F 2XX BTR, 0BB0F 2XX BTC,
0BA0F 4 2XM BTD, 0BA0F 5 2XM BTSD, ( ->reg ew,db)
0BA0F 6 2XM BTRD, 0BA0F 7 2XM BTCD,
0BC0F 2XX BSF, 0BD0F 2XX BSR, ( -> rw,ew)
\ 2XX-двойные-сдвиги. ->
0A40F 2XX SHLDD, 0AC0F 2XX SHRDD, ( rw,ew,db)
0A50F 2XX SHLDC, 0AD0F 2XX SHRDC, ( rw,ew)
\ 2DX-расширение-операнда. wrd-> r,e
0B60F 2DX MOVZX, 0BE0F 2DX MOVSX,
\ 2XX-нормальное умножение. -> rw,ew
0AF0F 2XX IMULX,
avatar
Gudleifr
Admin

Сообщения : 932
Дата регистрации : 2017-03-29

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: FORTH-ассемблер

Сообщение автор Gudleifr в Ср Июн 28, 2017 12:51 pm

Наконец, 32-разрядная адресация





\ Assembler. 80386. Новые регистры и операнды.
\ 1XX-новые префиксы. ->
064 1XX FS: 65 1XX GS: 66 1XX OS| 67 1XX AS|
\ Новые регистры.
4 CONSTANT FS 5 CONSTANT GS
200F 2DX MOVCR, 210F 2DX MOVDR, 240F 2DX MOVTR, ( dst-> rd,ed)
0A00F 2XX PUSHFS, 0A30F 2XX POPFS, ( ->)
0A80F 2XX PUSHGS, 0A90F 2XX POPGS,
0B20F 2XX LSS, 0B40F 2XX LFS, 0B50F 2XX LGS, ( -> rw,ed)
\ 32-разрядная адресация.
( mod.reg-> mod.reg.RM) 4 1SR [SB] 5 1SR [20]
: /*2 8 OR ; : /*4 10 OR ; : /*8 18 OR ; ( ind->sc.ind)
: [IB] ( sc.ind,bas->) SWAP 3 << OR C, ; ( sc.ind.bas,)

К счастью, она проще 16-разрядной.


Последний раз редактировалось: Gudleifr (Вс Июл 09, 2017 5:11 pm), всего редактировалось 2 раз(а)
avatar
Gudleifr
Admin

Сообщения : 932
Дата регистрации : 2017-03-29

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: FORTH-ассемблер

Сообщение автор Gudleifr в Ср Июн 28, 2017 12:52 pm

\ Assembler. 80486. P5. P6. Новые команды.
\ 80486. 2DX-перестановки.
0B00F 2DX CMPXCHG, ( wrd-> r,e) 0C80F 2DX BSAP, ( reg->)
0C00F 2DX XADD, ( wrd-> r,e)
\ 80486. Кэшевые.
80F 2XX INVD, 90F 2XX WBINVD, ( ->)
10F 7 2XM INVLPG, ( ->111 e)
\ P5.
0C70F 1 2XM CMPXCHG8B, ( ->reg eq) 0A20F 2XX CPUID, ( ->)
310F 2XX RDTSC, 320F 2XX RDMSR, ( ->)
300F 2XX WRMSR, 0AA0F 2XX RSM, ( ->)
\ P6.
400F 2DX CMOV, ( cond->) 330F 2XX RDPMC, ( ->)
0B0F 1DX UD2, ( ->)

\ Assembler. MMX. В основном, [+wrd]-> mmx,eq
2 CONSTANT /DO 3 CONSTANT /QO ( для +wrd, см. прим. ниже)
6E0F 2XX MOVXMD, 7E0F 2XX MOVMXD, 6F0F 2XX MOVXMQ,
7F0F 2XX MOVMXQ, 630F 2XX PACKSSDB, 6B0F 2XX PACKSSDW,
670F 2XX PACKUSWB, 0DB0F 2XX PAND, 0DF0F 2XX PANDN,
0F50F 2XX PMADDWD, 0E50F 2XX PMULHW, 0D50F 2XX PMULLW,
0EB0F 2XX POR, 0EF0F 2XX PXOR,
0FC0F 2DX PADD, 740F 2DX PCMPEQ, 640F 2DX PCMPGT, ( bwd)
0F80F 2DX PSUB, 680F 2DX PUNPCKH, 680F 2DX PUNPCKL, ( bwd)
0EC0F 2DX PADDS, 0DC0F 2DX PADDUS, 0E80F 2DX PSUBS, ( bw) 10 0D80F 2DX PSUBUS, ( bw)
0F00F 2DX PSLL, 0D00F 2DX PSRL, ( wdq)
0E00F 2DX PSRA, ( wd)
700F 6 2DM PSLLD, 700F 2 2DM PSRLD, ( wdq->reg eq,db)
700F 4 2DM PSRAWD, ( wd->reg eq,db)
770F 2XX EMMS, ( ->)

Думаю, принцип понятен...
avatar
Gudleifr
Admin

Сообщения : 932
Дата регистрации : 2017-03-29

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: FORTH-ассемблер

Сообщение автор Gudleifr в Ср Июн 28, 2017 12:53 pm

Ах, да мы забыли про арифметический сопроцессор.

\ Assembler. 8087. Команды без параметров. ->
0EED9 2XX FLDZ, 0E8D9 2XX FLD1, 0EBD9 2XX FLDPI,
0E9D9 2XX FLDL2T, 0EAD9 2XX FLDL2E, 0ECD9 2XX FLDLG2,
0EDD9 2XX FLDLN2, ( Загрузки констант)
0F4D9 2XX FXTRACT, 0E1D9 2XX FABS, 0E0D9 2XX FCHS,
0FAD9 2XX FSQRT, 0FDD9 2XX FSCALE, 0F8D9 2XX FPREM,
0FCD9 2XX FRNDINT, ( Арифметические)
0D9DE 2XX FCOMPP, 0E4D9 2XX FTST, 0E5D9 2XX FXAM, ( Сравн.)
0F2D9 2XX FPTAN, 0F3D9 2XX FPATAN, 0F0D9 2XX F2XM1,
0F9D9 2XX FYL2XP1, 0F1D9 2XX FYL2X, ( Трансцендентные)
0E0DB 2XX FENI, 0E2DB 2XX FCLEX, 0E1D8 2XX FDISI,
0E3DB 2XX FINIT, 0F6D9 2XX FDECSTP, 0F7D9 2XX FINCSTP,
0D0D9 2XX FNOP, ( Управления)

\ Assembler. 8087. Адресные команды 1. ->reg e
0DF 0 1XM FILDW, 0DB 0 1XM FILDD, 0DF 5 1XM FILDQ,
0DF 4 1XM FBLD, 0D9 0 1XM FLDD, 0DD 0 1XM FLDQ,
0DB 5 1XM FLDT, 0D9 2 1XM FSTD, 0DD 2 1XM FSTQ,
0D9 3 1XM FSTPD, 0DD 3 1XM FSTPQ, 0DD 7 1XM FSTPT,
0DF 6 1XM FBSTP, 0DF 2 1XM FISTW, 0DB 2 1XM FISTD,
0DF 3 1XM FISTPW, 0DB 3 1XM FISTPD, 0DF 7 1XM FISTPQ, ( Пер.)
0D8 6 1XM FDIVD, 0DC 6 1XM FDIVQ, 0DE 6 1XM FIDIVW,
0DA 6 1XM FIDIVD, 0D8 7 1XM FDIVRD, 0DC 7 1XM FDIVRQ,
0DE 7 1XM FIDIVRW, 0DA 7 1XM FIDIVRD, 0D8 0 1XM FADDD,
0DC 0 1XM FADDQ, 0DE 0 1XM FIADDW, 0DA 0 1XM FIADDD,
0D8 1 1XM FMULD, 0DC 1 1XM FMULQ, 0DE 1 1XM FIMULW,
0DA 1 1XM FIMULD, 0D8 4 1XM FSUBD, 0DC 4 1XM FSUBQ,
0DE 4 1XM FISUBW, 0DA 4 1XM FISUBD, 0D8 5 1XM FSUBRD,
0DC 5 1XM FSUBRQ, 0DE 5 1XM FISUBRW, 0DA 5 1XM FISUBRD, ( Ар.)

\ Assembler. 8087. Адресные команды 2. ->reg e
0D8 2 2XM FCOMD, 0DC 2 2XM FCOMQ, 0D8 3 2XM FCOMPD,
0DC 3 2XM FCOMPQ, 0DE 2 2XM FICOMW, 0DA 2 2XM FICOMD,
0DE 3 2XM FICOMPW, 0DA 3 2XM FICOMPD, ( Сравнения)
0D9 4 2XM FLDENV, 0DD 4 2XM FRSTOR, 0D9 5 2XM FLDCW,
0D9 6 2XM FSTENV, 0D9 7 2XM FSTCW, 0DD 5 2XM FSTSW,
0DD 6 2XM FSAVE, ( Управления)

\ Assembler. 8087. Регистровые команды. reg->
0C0D9 2DX FLD, 0D0DD 2DX FST, 0D8DD 2DX FSTP,
0C8D9 2DX FXCH, ( Пересылки)
0F0D8 2DX FDIV0, 0F8DC 2DX FDIV, 0F8DE 2DX FDIVP,
0F8D8 2DX FDIVR0, 0F0DC 2DX FDIVR, 0F0DE 2DX FDIVRP,
0C0D8 2DX FADD0, 0C0DC 2DX FADD, 0C0DE 2DX FADDP,
0C8D8 2DX FMUL0, 0C8DC 2DX FMUL, 0C8DE 2DX FMULP,
0E0D8 2DX FSUB0, 0E8DC 2DX FSUB, 0E8DE 2DX FSUBP,
0E8D8 2DX FSUBR0, 0E0DC 2DX FSUBR, 0E0DE 2DX FSUBRP, ( Арифм.)
0D0D8 2DX FCOM, 0D8D8 2DX FCOMP, ( Сравнения)
0C0DD 2DX FFREE, ( Управления)

\ Assembler. 80X87. Новые команды.
\ Новые функции.
0F5D9 2XX FPREM1, 0FFD9 2XX FCOS, 0FED9 2XX FSIN,
0FBD9 2XX FSINCOS,
\ Сравнение.
0E0DD 2DX FUCOM, 0E8DD 2DX FUCOMP, 0E9DA 2XX FUCOMPP,
\ Управление.
0E0DF 2XX FSTSWAX,
\ P6. Сравнение. reg->
0C0DA 2DX FCMOVCY, 0C8DA 2DX FCMOVZR, 0D0DA 2DX FCMOVCY|ZR,
0D8DA 2DX FCMOVPE, 0C0DB 2DX FCMOVNC, 0C8DB 2DX FCMOVNZ,
0D0DB 2DX FCMOVNC&NZ, 0D8DB 2DX FCMOVPO,
0F0DB 2DX FCOMI, 0F0DF 2DX FCOMIP, 0E8DB 2DX FUCOMI,
0E8DF 2DX FUCOMIP,


Последний раз редактировалось: Gudleifr (Вс Апр 08, 2018 11:38 am), всего редактировалось 1 раз(а)
avatar
Gudleifr
Admin

Сообщения : 932
Дата регистрации : 2017-03-29

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: FORTH-ассемблер

Сообщение автор Gudleifr в Ср Июн 28, 2017 12:53 pm

Ну, как-то так. Я опустил аналогичные описанным Барановых & Ноздруновым слова для упаковки кода в словарные статьи и макросы условных переходов.

Как выглядит использование этой лабуды на практике (из Win-FOBOS)?

Слово I для цикла DO (сугубо ВНУТРЕННЕЕ КОДОВОЕ СЛОВО):

CODE I ( -- n) B PUSHR, /DW MOV, B BP [8] -4 C, NEXT, END-CODE

Вызов WIN-API функций (ВНЕШНЕЕ):

CODE CALL ( ..., a -- w)
/WO MOV, BP [DW] EBP-OLD ,
/WO MOV, DI [DW] EDI-OLD ,
CALLEW, B [RG] /DW MOV, B A [RG]
/DW MOV, DI [DW] EDI-OLD , NEXT,
END-CODE

Компиляция строки (скорее, ВВНУТРЕННЕЕ):

CODE (S") ( -- ca, n) ( СТРОКА ДЛИНА)
B PUSHR, /DW MOV, B SI [RG] B INCR, B PUSHR,
/BO MOVZX, A SI [0] /DW MOV, B A [RG]
/DW ADD, SI A [RG] SI INCR, NEXT, END-CODE
: S" ( <строка"> -- ca, n) STATE @ IF COMPILE (S") THEN
34 WORD DUP C@ 1+ ALLOT STATE @ IF DROP ELSE COUNT THEN ; IMMEDIATE

Кстати, слово NEXT, (переход к следующему шитому коду), очевидно, входит в само FORTH-ядро (ПСЕВДОСЛОВО, изначально реализованное ассемблерным макросом).


Последний раз редактировалось: Gudleifr (Вс Апр 08, 2018 11:39 am), всего редактировалось 1 раз(а)
avatar
Gudleifr
Admin

Сообщения : 932
Дата регистрации : 2017-03-29

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: FORTH-ассемблер

Сообщение автор Gudleifr в Ср Июн 28, 2017 12:56 pm

ВЫВОДЫ.

Написав свой FORTH-ассемблер (DOS-FOBOS), я вдруг заметил, что предпочитаю им не пользоваться, разве что для 32-разрядных участков кода. Для вставки обычных КОДОВЫХ СЛОВ (что ВНЕШНИХ, что ВНУТРЕННИХ) гораздо проще было внести изменения (ПСЕВДОСЛОВА) в ассемблерный код самого FOBOS и перекомпилировать его. Мур-то был прав!

Так что я знаю только две причины применения FORTH-ассемблера:
1) вам удалось написать замкнутую FORTH-систему, в которой можно удобно работать и программировать, не вылезая наружу - во внешнюю Операционную Систему, или
2) вам нужно писать код для процессора (режима), который ваше ПО сборки самой FORTH-системы не поддерживает.
***

Боле того, начав дергать для примера блоки из DOS-FOBOS, я обнаружил, что в конце моего ассемблера была пара блоков с "полезными" макросами часто встречающихся случаев адресации. Интересно, я, хотя бы раз их использовал? Или написал и сразу забыл?
Нет, писать что-то заранее на FORTH, который сам не имеет смысла писать заранее, это вдвойне бесполезная трата времени.
avatar
Gudleifr
Admin

Сообщения : 932
Дата регистрации : 2017-03-29

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: FORTH-ассемблер

Сообщение автор Спонсируемый контент


Спонсируемый контент


Вернуться к началу Перейти вниз

Вернуться к началу


 
Права доступа к этому форуму:
Вы не можете отвечать на сообщения