Current time: 23.03.2024, 17:21 Hello There, Guest! (LoginRegister)
Language: english | russian  

Post Reply 
Threaded Mode | Linear Mode
2B (Дваб)
» Форумный язык программирования (Фяп)
Author Message
Berserker Offline
Administrators

Posts: 16449
Post: #1

   Введение.
   Дваб предназначен для написания текстовых консольных игр и утилит. Код программы, записанный обычным текстом, транслируется в код виртуальной машины, на которой и выполняется. Виртуальная машина - это своего рода песочница, призванная защитить пользователя от возможных попыток взлома или нанесения вреда. Единственная внешняя информация, доступная программам, кроме ввода пользователя, это его ник на форуме (Guest, если гость). Виртуальная машина работает на компьютере пользователя и реализована средствами встроенного в бразуер языка обработки сценариев JavaScript.

   Структура виртуальной машины (ВМ).
   ВМ построена на стёковой основе. Стёк - это список элементов, над которым определено всего две операции: добавить элемент в конец списка и получить последний элемент списка, удалив его из структуры. Стёк не имеет размеров, точнее он ограничен лишь размерами оперативной памяти пользователя. Для того, чтобы поместить элемент в стёк, достаточно лишь назвать его:
Code:
1 2 3

   После выполнения кода стёк будет содержать элементы 1, 2, 3.
   Все команды ВМ получают аргументы с вершины стёка. Например, команда сложения чисел (а также объединения строк) "add" сперва достаёт с вершины два элемента, складывает их, а затем помещает результат в стёк. Также работает и большинство других команд.
Code:
4 6 add

   После выполнения кода в стёке будет лишь одно число: 10.

   Переменные.
   В отличие от константных значений, коими являются строки ('5' или 'heh' или "привет"), числа (0, 6.777, -12), логические значения (true - истина, false - ложь) существует ещё ячейки памяти со своими собственными именами, чьи значения могут меняться по ходу выполнения программ. Такие ячейки памяти называются переменными.
Code:
'МояПерваяПеременная' var

   Создаст в текущем контексте переменную с именем "МояПерваяПеременная" и начальным значением 0. Если бы в коде кавычки были опущены, то смысл был бы иной: положить значение переменной в стёк.

   Поток управления программы.
   Редко когда логика программы не содержит условий или циклов. В двабе управление потоков программы реализовано на низком уровне, близком к ассемблеру, при помощи условных переходов и меток. Рассмотри в начале объявление меток и переходы на них.
Code:
1
4
"метка" jmp
6
:метка
add

   Что окажется на вершине стёка после выполнения данного кода? Давайте посмотрим по шагам. 1 - положили единицу в стёк. 4 - положили 4 в стёк (стёк: 1, 4). "метка" - положили строку в стёк (стёк: 1, 4, "метка"). jmp - команда перехода на метку с указанным именем. С вершины стёка достаётся значение "метка", затем ВМ определяет её адрес и переходит прямо к позиции :метка, минуя "положить в стёк 6". Далее команда сложения достанет верхние аргументы (1, 4) и положит в стёк результат сложения (5).
   Вывод: для объявления метки необходимо поставить знак двоеточия, за которым незамедлительно написать имя метки без кавычек.
   
   Условные переходы. Допустим, мы хотим написать простую программу, определяющую, какое число ввёл пользователь (для простоты будем считать, что пользователь введёт корректное число). Программа должна возвратить: "положительное" - если число > 0, "отрицательное", если число < 0 и "нуль" - если число = 0. В примере ниже используются две функции работы с консолью: read - читает ввод пользователя и помещает его в стёк, write - выводит строку на экран. Функция dup помещает в стёк копию верхнего элемента.
Code:
clrscr; очищаем экран
read; считываем число с клавиатуры
dup; помещаем его копию на вершину стёка
0; число, с которым сравниваем
>; команда возвращает логическое значение сравнения двух верхних элементов стёка (равносильно считанное_число > 0?)
'НеПоложительное'; имя метки для перехода
jf; перейти на метку если условие ложно (Jump if False)
'Положительное'; результат
'Вывод' jmp; безусловный переход к выводу результата на экран
:НеПоложительное
dup 0 <; проверяем, может быть число меньше нуля?
'РавноНулю' jf; если нет, значит равно нулю и переходим на соответствующую метку
; иначе
'Отрицательное'; результат
'Вывод' jmp; безусловный переход к выводу результата на экран
:РавноНулю
'Нуль'; результат
:Вывод
clrscr; очищаем экран
write; выводим результат

   Циклы или повторяемые действия.
   Предположим, мы хотим вывести на экран числа 1..10. Вариант "в лоб" мы даже не рассматриваем (1 write 2 write 3 write...).
Code:
'i' var; объявили переменную- счётчик цикла
1 'i' mov; присвоили переменной начальное значение 1
:Цикл
i dup write; выводим текущее значение счётчика
1 add dup 'i' mov; увеличили счётчик на 1
10 > 'Цикл' jf; повторить, пока счётчик не зайдёт за 10

   Подпрограммы и контексты.
   Линейный код рано или поздно разрастается и становится трудночитаем. На лицо необходимость разбить его на простые и понятные блоки - подпрограммы. Подпрограмму можно вызвать, передав её определённые параметры (через наш универсальный стёк). Она в свою очередь тоже может вернуть результат. Возврат из подпрограммы переводит поток управления на следующую команду после той, что вызвала подпрограмму. Важно свойство подпрограмм - то, что они обладают своим набором переменных. Все переменные, которые будут объявлены в подпрограмме, по возврату из неё будут уничтожены. Глобальными переменными называются те, которые были объявлены на самом высоком уровне. К ним есть доступ из любой подпрограммы. Однако если вы объявили глобальную переменную А, а потом локальную А, то все обращения к А в подпрограмме будут касаться только локальной переменной. Иными словами вы перекрыли область видимости переменной.
   Пример подпрограммы, сравнивающей два числа и возвращающей ("Больше", "Меньше" или "Равно")
Code:
'start' jmp; переходим на начало программы, минуя блок подпрограмм
; Подпрограмма Сравнить (a, b)
:Сравнить
'b' var 'b' mov; переменная b теперь содержит аргумент b
'a' var 'a' mov; переменная a содержит аргумент а
a b > 'НеБольше' jf
'Больше'
ret; команда возврата из подпрограммы
:НеБольше
a b < 'Равно' jf
'Меньше'
ret
:Равно
'Равно'
ret

:start
clrscr
'Введите первое число: ' write read nl write
num dup isnan 'Ошибка' jt
'Введите второе число: ' write read nl write
num dup isnan 'Ошибка' jt
'Сравнить' call
ret
:Ошибка
'Некорректный ввод!' write


Скачать Герои 3 Эра и всё, что с ней связано / ERA 2.46f для старых модов
Поддержать проект
22.08.2010 19:23
Find all posts by this user Quote this message in a reply
« Next Oldest | Next Newest »
Post Reply 


Messages In This Thread
2B (Дваб) - Berserker - 22.08.2010 19:23
RE: 2B (Дваб) - Berserker - 22.08.2010, 20:31

Forum Jump:

Powered by MyBB Copyright © 2002-2024 MyBB Group