Компьютерная архитектура iiixmish2
Введение
[править]Определения
[править]- Регистр процессора
- Регистр процессора — это поле определённой длины, которое находится в памяти процессора. Доступ к регистру очень быстр, его содержимое можно сохранить в память и обратно. Бывает как доступен из программы, так и нет.
- Язык ассемблера
Код на Си и как он может выглядеть на языке ассемблера (переменная variable по адресу 8699999) variable = 5;
mov %R_FA_0%, 5 isv %R_FA_0%, 8699999
- Ассемблерная директива
- Ассемблерная директива («псевдокоманда») — это, можно сказать, команда ассемблера. Директивы влияют на компиляцию программы. Примеры в Makexm2c —
.goto
,.ascii
и.def
.
Учебник
[править]Данный учебник учит программированию на Makexm2c.
Makexm2c
[править]Makexm2c — это язык ассемблера, предназначенный для создания программ для виртуальной машины «iiixmish2». Если Вы являетесь опытным программистом, то можете найти Makexm2c более лёгким, чем другие низкоуровневые языки.
iiixmish2
[править]Iiixmish2 — это 32-разрядная виртуальная машина со своими командами и др. Она имеет 10 миллионов ячеек памяти, 44 пользовательских регистров, 2000 ячеек видеопамяти, более 35 команд и экран 640 × 480 (но может отображаться меньше).[1]
Ниже представлены названия iiixmish2-инструкций и соответствующие signed char
-опкоды[2]:
Название | Код операции |
---|---|
NOP[3] |
-1 |
ADD |
-2 |
SUB |
-3 |
MOV |
-4 |
ILD |
-5 |
VLD |
-6 |
LD |
-7 |
ISV |
-8 |
VSV |
-9 |
SLP |
-10 |
IFA |
-11 |
IFB |
-12 |
IFC |
-13 |
IFD |
-14 |
UPDD |
-15 |
OFF |
-16 |
VRST |
-17 |
JMP |
-18 |
MUL |
-21 |
DIV |
-22 |
LSLP |
-23 |
CUR |
-24 |
VSTR |
-25 |
INC |
-26 |
DEC |
-27 |
TNP |
-28 |
MOD |
-29 |
EXP |
-30 |
MOV2 |
-31 |
MOV3 |
-35 |
VSVAN |
-36 |
IFE |
-37 |
LSHIFT |
-38 |
RSHIFT |
-39 |
XOR , OR , AND |
-40, -41, -42 |
TIME |
-43 |
TRST |
-44 |
Получение необходимого
[править]Скачайте свободную реализацию iiixmish2 здесь, а также ассемблер здесь. Раньше мы предлагали читателям загрузить makexm2c-tools, но сейчас он устарел. Ассемблер, входящий в старый комплект, был заменён новым и быстрым mxm2c-as.
Распакуйте полученные архивы. Скомпилируйте программы, используя OpenJDK 17 и GCC. В Debian, Вы можете установить его, выполнив следующую команду:
$ sudo apt install openjdk-17-jdk
Выполните java --version
.
Синтаксис
[править]Makexm2c-программы могут состоять из команд:
<название> [<аргумент 0>[[,] <аргумент 1>]…]
, псевдокоманд (директив):
.<название> [<аргумент 0>[ <аргумент 1>]]
, меток:
<название>:
и комментариев.
К регистрам можно подставлять «UR» (UR0, UR1…).
Теперь мы можем написать программу «Hello, world!», она будет выводить на экран виртуальной машины «Hello, world!» (перевод — «Всем привет!», а буквально — «Здравствуй, мир!»). Программа подобна загрузчику: она выполняется практически сразу после запуска машины и не требует для своей работы операционной системы.
Создайте файл «hello.asm» и вставьте в него следующее:
vstr 0000, "Hello, world!"
updd
Это код на Makexm2c, переведите его в код, понятный виртуальной машине iiixmish2, используя ассемблер:
$ mxm2c-as hello.asm hello
Отлично! Запустите iiixmish2, передав полученный файл:
$ java downadow.iiixmish2.main.Iiixmish2 hello --no-communication
Параметр --no-communication отключает, возможно, губительную для SSD-дисков коммуникацию. Если требуется, опустите данный параметр, включение и выключение коммуникации контролируется клавишами F2 и F3.[4]
Код нашей программы состоит из двух команд — vstr
и updd
.
vstr
[править]Команда vstr
нужна для вывода строки на экран. Конечно, это можно сделать и без неё, но с ней это делается проще и эффективнее: сокращается размер программы. Имеет два аргумента:
Синтаксис | Описание |
---|---|
ЦЦЦЦ (Ц — цифра) |
Адрес ячейки видеопамяти, с которого будет располагаться строка |
"СТРОКА" |
СТРОКА для вывода |
updd
[править]Команда для обновления («перерисовки») экрана.
Регистры
[править]Как уже было сказано ранее, iiixmish2 имеет 44 пользовательских регистров (п. реги́стры).
2, 3 и 4 п. регистры предназначены для обновления экрана, п. регистр 1 хранит нажатую клавишу. Избегайте использования п. регистра 5, т. к. он может использоваться некоторыми командами.[2]
Присваивание
[править]Команда mov
сохраняет число в п. регистр, число не должно превышать один байт. Аргументы:
Синтаксис | Описание |
---|---|
ЧИСЛО |
АДРЕС п. регистра, который должен принять ЧИСЛО |
ЧИСЛО |
ЧИСЛО для сохранения |
Пример использования:
mov UR10, 64
Также можно вставлять 'СИМВОЛ'
вместо числа, пример:
mov UR10, 'j'
то же, что и
mov UR10, 106
Сложение
[править]Команда add
складывает два п. регистра, сохраняет результат в п. регистр. Аргументы:
Синтаксис | Описание |
---|---|
ЧИСЛО |
адрес п. регистра, содержащего первое слагаемое |
ЧИСЛО |
адрес п. регистра, содержащего второе слагаемое |
ЧИСЛО |
адрес п. регистра, в который следует поместить сумму |
Пример использования:
add UR0 UR6, UR9
Запятые между аргументами и «UR» к адресам, — необязательны.
Вычитание
[править]Команда sub
вычитает из п. регистра значение другого п. регистра, результат сохраняется в п. регистр.
Аргументы:
Синтаксис | Описание |
---|---|
ЧИСЛО |
адрес п. регистра, содержащего уменьшаемое |
ЧИСЛО |
адрес п. регистра, содержащего вычитаемое |
ЧИСЛО |
адрес п. регистра, в который следует поместить разность |
Пример использования:
sub UR6 UR8, UR0
Загрузка
[править]Команда ld
загружает значение п. регистра в другой п. регистр.
Аргументы:
Синтаксис | Описание |
---|---|
ЧИСЛО |
адрес п. регистра, который следует загрузить в ДРУГОЙ п. регистр |
ЧИСЛО |
адрес ДРУГОГО п. регистра |
Пример использования:
ld UR1, UR0
Умножение
[править]Команда mul
умножает п. регистр на другой п. регистр, результат сохраняется в п. регистр.
Аргументы:
Синтаксис | Описание |
---|---|
ЧИСЛО |
адрес п. регистра, содержащего множимое |
ЧИСЛО |
адрес п. регистра, содержащего множитель |
ЧИСЛО |
адрес п. регистра, в который следует поместить произведение |
Пример использования:
mul UR6 UR8, UR0
Деление
[править]Команда div
делит п. регистр на другой п. регистр, результат сохраняется в п. регистр.
Аргументы:
Синтаксис | Описание |
---|---|
ЧИСЛО |
адрес п. регистра, содержащего делимое |
ЧИСЛО |
адрес п. регистра, содержащего делитель |
ЧИСЛО |
адрес п. регистра, в который следует поместить частное |
Пример использования:
div UR6 UR8, UR0
Получение остатка от деления
[править]Команда mod
делит п. регистр на другой п. регистр, остаток сохраняется в п. регистр.
Аргументы:
Синтаксис | Описание |
---|---|
ЧИСЛО |
адрес п. регистра, содержащего делимое |
ЧИСЛО |
адрес п. регистра, содержащего делитель |
ЧИСЛО |
адрес п. регистра, в который следует поместить остаток |
Пример использования:
mod UR0 UR29, UR8
Команда inc
увеличивает п. регистр на единицу. Пример использования:
inc UR0
Команда dec
уменьшает п. регистр на единицу. Пример использования:
dec UR0
Изменение знака
[править]Команда tnp
изменяет знак п. регистра, пример использования:
tnp UR14
Пример:
exp UR0 UR6, UR8
mov2
[править]Команда mov2
выполняет то же, что и mov
, но размер второго аргумента увеличен до шести байтов.
Аргументы:
Синтаксис | Описание |
---|---|
ЧИСЛО |
адрес п. регистра |
ЦЦЦЦЦЦЦ |
число для сохранения |
Пример использования:
mov2 UR0, 0004985
mov3
[править]Команда mov3
«склеивает» п. регистры как строки, сохраняет результат в п. регистр.
Аргументы:
Синтаксис | Описание |
---|---|
ЧИСЛО |
адрес п. регистра, в который следует сохранить результат |
ЧИСЛО |
адрес первого п. регистра для «склеивания» |
ЧИСЛО |
адрес второго п. регистра для «склеивания» |
ЧИСЛО |
адрес третьего п. регистра для «склеивания» |
ЧИСЛО |
адрес четвёртого п. регистра для «склеивания» |
ЧИСЛО |
адрес пятого п. регистра для «склеивания» |
ЧИСЛО |
адрес шестого п. регистра для «склеивания» |
Пример использования:
mov3 UR0, UR29 UR28 UR27 UR26 UR25 UR24
Сдвиг
[править]Следующий код выполняет операцию вида UR20 << UR19 (сдвиг битов влево) и сохраняет результат в UR8:
lshift UR20 UR19, UR8
UR8 = UR20 >> UR19
:
rshift UR20 UR19, UR8
Для побитовых XOR, OR и AND, используйте одноимённые инструкции.
Получение времени
[править]Операция time
копирует в заданный регистр кол-во миллисекунд, приблизительно начиная от запуска процессора. Принимает один аргумент. trst
сбрасывает время.
Комментарии
[править]Коммента́рии — это тексты в коде программы, которые не влияют на её работу, но, как правило, помогают лучше понять её. В Makexm2c нет обязательного спецсимвола, который отличал бы комментарии от команд.[5]
Ме́тки — в Makexm2c — это мнемоники, которые ставятся в определённые места в коде программы. Обращение к метке вставляет на месте обращения адрес, по которому располагается эта метка в двоичной форме программы. Пример:
метка:
nop
nop
mov2 UR0, <метка>
Для обращения, название метки, заключённое в <
и >
, вставляется в нужное место в программе.
Для создания именованных констант используется директива .def
, пример:
.def %CONST% "0"
создаст именованную константу «CONST» со значением «0».
Обращение к именованным константам отличается от обращения к меткам лишь тем, что название заключается в %
, а не <
и >
.
Задание
Потренируйтесь с пройденными командами.
В iiixmish2 есть команды для создания условных переходов. Рассмотрим, как использовать их в Makexm2c.
Равно
[править]В iiixmish2 нет инструкций вроде BRz, BRn и т. д., ветвление реализуется посредством команд IFA, IFB, IFC, IFD и IFE. Для создания перехода вроде «если значение п. регистра А равно значению регистра Б, то выполнить переход на <значение п. регистра В>», воспользуйтесь следующей конструкцией:
if АДРЕС0 == АДРЕС1, АДРЕС2
Название | Описание |
---|---|
АДРЕС0 |
адрес первого п. регистра для сравнения |
АДРЕС1 |
адрес второго п. регистра для сравнения |
АДРЕС2 |
адрес п. регистра, на значение которого нужно перейти |
Ясно? Идём дальше.
Неравно
[править]if АДРЕС0 != АДРЕС1, АДРЕС2
Больше
[править]if АДРЕС0 > АДРЕС1, АДРЕС2
Меньше
[править]if АДРЕС0 < АДРЕС1, АДРЕС2
Равно ×2
[править]if АДРЕС0 == АДРЕС1 && АДРЕС2 == АДРЕС3, АДРЕС4
(если п. регистры АДРЕС0
и АДРЕС1
равны, п. регистры АДРЕС2
и АДРЕС3
равны, то выполнить переход на <значение п. регистра АДРЕС4
>)
Видеопамять
[править]Как уже говорилось во введении, iiixmish2 имеет 2000 ячеек видеопамяти.
Почти все ячейки видеопамяти могут отображаться на экране. Последние две ячейки, — 1998-ая и 1999-ая, — хранят параметр цвета для фона и параметр цвета для отображаемых ячеек видеопамяти. Возможные цвета[2]:
Значение | Цвет |
---|---|
1 | белый |
2 | зелёный |
3 | голубой или синий |
4 | тёмно-зелёный |
5 | серый |
6 | красный |
7 | жёлтый |
иное | чёрный |
Пример изменения цвета отображаемых ячеек видеопамяти на жёлтый:
mov UR0, 7
vsv UR0, 1999
Для загрузки значения из видеопамяти в п. регистр, используйте команду vld
. Её аргументы:
Синтаксис | Описание |
---|---|
ЦЦЦЦ |
адрес ячейки видеопамяти для загрузки |
ЧИСЛО |
адрес п. регистра-приёмника |
Пример использования:
vld 0001, UR8
Для сохранения значения п. регистра в ячейку видеопамяти, используйте vsv
. Аргументы:
Синтаксис | Описание |
---|---|
ЧИСЛО |
адрес п. регистра для сохранения |
ЦЦЦЦ |
адрес нужной ячейки видеопамяти |
Пример использования:
vsv UR0, 0063
Для сохранения значения п. регистра в видеопамять как число, используйте vsvan
. Аргументы:
Синтаксис | Описание |
---|---|
ЧИСЛО |
адрес п. регистра для сохранения |
ЦЦЦЦ |
адрес ячейки видеопамяти, с которой следует начать запись |
Пример использования:
vsvan UR0, 0000
Вы также можете вписывать адрес п. регистра вместо ЦЦЦЦ
в аргументах этих команд (такое поддерживается в Makexm2c). Так, vsv UR0, UR16
сохранит содержимое п. регистра 0 в яч. видеопамяти, адрес которой находится в регистре 16.
Вы можете печатать разными цветами! Для этого, измените ячейку видеопамяти, на месте которой будет изменение цвета последующих, на 255 плюс нужное значение цвета.[2]
Текст в самой нижней строке отображается полужирным.
Задание
Напишите программу, которая складывает два числа и выводит результат на экран.
Память
[править]Программы iiixmish2 загружаются в его па́мять (насколько это возможно).[2]
Команда ild
предназначена для загрузки значений из памяти в п. регистры. Аргументы:
Синтаксис | Описание |
---|---|
ЦЦЦЦЦЦЦ |
адрес ячейки памяти для загрузки |
ЧИСЛО |
адрес п. регистра-приёмника. |
Пример использования:
ild 6001900, UR0
Для сохранения значения п. регистра в память, используйте isv
. Аргументы:
Синтаксис | Описание |
---|---|
ЧИСЛО |
адрес п. регистра для сохранения |
ЦЦЦЦЦЦЦ |
адрес нужной ячейки памяти |
Пример использования:
isv UR10, 0999999
Вы можете вписывать адрес п. регистра вместо ЦЦЦЦЦЦЦ
в аргументах этих команд.
Недостаток vstr
[править]Максимальное значение символа в vstr
-строке ограничено одним байтом[2], т. е. вы не можете печатать дополнительные символы на экран iiixmish2, используя эту команду (например, буквы русского алфавита). Длина vstr-строки не должна превышать один знаковый байт (signed char
).
Вы можете придумать свои средства для печати символов Юникода. Мы рекомендуем Вам (по возможности) писать на высокоуровневых языках. См. XMConC.
Простая программа
[править]Ниже представлен пример программы, в которой пользователь может вводить данные. То, что от символа «;» до конца строки будет комментарием.
mov UR29, 30
mov2 UR28, <main>
main:
; ждать 30 миллисекунд
lslp UR29
; если клавиша не была нажата, то перейти к main
if UR1 == UR0, UR28
; сохраняем клавишу (указателем текущей ячейки будет п. регистр 27)
vsv UR1, UR27
; увеличиваем указатель
inc UR27
; сбрасываем нажатую клавишу
mov UR1, 0
; обновляем экран
updd
; переход к main
jmp UR28
Задание
Измените программу так, чтобы фон стал белым, а текст, вводимый пользователем, — чёрным. Помните, как собирать и запускать программы?
Ещё директивы
[править].ascii <mem0> "hello world"
приказывает ассемблеру записать строку «hello world», начиная с яч. <mem0> (адрес метки mem0). .goto +100
приказывает перейти ассемблеру на 100 яч. больше, это похоже на 100 nop'ов. .byte ЧИСЛО
вставит десятичное ЧИСЛО. .orig 1000
выполнит переход к ячейке 1000.
Общение с другими компьютерами
[править]Iiixmish2 и другие компьютеры (включая ЭВМ, на котором выполняется iiixmish2) могут «общаться» через файлы коммуникации. Данные, которые передал компьютер, сохраняются в памяти iiixmish2, начиная с адреса 9999872. Чтобы ответить, запишите краткий ответ, начиная с адреса 9999000.
Это последний раздел изучения. В нём описываются команды slp
, off
, vrst
.
slp
[править]slp
ждёт <значение п. регистра А> секунд (для миллисекунд есть lslp
). Пример использования:
slp UR0
off
[править]off
завершает работу iiixmish2.
vrst
[править]vrst
заменяет значения почти всех ячеек видеопамяти на неотображаемое (0), предназначение — убрать текст с экрана. Не путайте его с vstr
.