Компьютерная архитектура iiixmish2

iiixmish2


Введение

Определения

Регистр процессора
Регистр процессора — это поле определённой длины, которое находится в памяти процессора. Доступ к регистру очень быстр, его содержимое можно сохранить в память и обратно. Бывает как доступен из программы, так и нет.
Язык ассемблера
Язык ассемблера — это низкоуровневый язык программирования, максимально приближённый к командам самого процессора.
Ассемблерная директива
Ассемблерная директива («псевдокоманда») — это команда ассемблера. Директивы влияют на компиляцию программы. Примеры в Makexm2c — .skip, .ascii и .def.

Учебник

Данный учебник учит программированию на Makexm2c.

Makexm2c

Makexm2c — это язык ассемблера, предназначенный для создания программ под iiixmish2. Бо́льшая часть команд Makexm2c представляет собой мнемонические обозначения инструкций iiixmish2. Важно упомянуть, что в большинстве инструкций типы параметров определены. Например, для add применимы только регистры; для mov — регистр и константа.

iiixmish2

Iiixmish2 — это 32-разрядная компьютерная архитектура. Она имеет >=10 миллионов ячеек памяти, 44 пользовательских регистров, 2000 ячеек видеопамяти, более 30 команд и экран 63x30 символов.[1]

Ниже представлены названия iiixmish2-инструкций и соответствующие signed char-опкоды[2]:

Название Код операции
ADD -2
SUB -3
MOV -4
ILD -5
VLD -6
LD -7
ISV -8
VSV -9
CALL -10
IFA -11
IFB -12
IFC -13
IFD -14
UPDD -15
OFF -16
VRST -17
JMP -18
MUL -21
DIV -22
INC -26
DEC -27
TNP -28
MOD -29
LSHIFT -38
RSHIFT -39
XOR, OR, AND -40, -41, -42
TIME -43
TRST -44
RISV -45
RVSV -46
RILD -47
RVLD -48

Получение необходимого

Скачайте свободную реализацию 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.s» и вставьте в него следующее:

mov UR0, <main>
jmp UR0

;;;;;  данные  ;;;;;

str:
    .skip 12
    .ascii <str> "hello, world"
    .byte 0

;;;;;;;;;;;;;;;;;;;;

main:
    mov UR0, <str>
    mov UR6, 0
loop:
    ild UR0, UR8
    mov UR10, 0
    mov UR11, <final>
    if UR8 == UR10, UR11
    vsv UR8, UR6
    inc UR0
    inc UR6
    mov UR11, <loop>
    jmp UR11
final:
    updd

Это код на Makexm2c, переведите его в код, понятный iiixmish2, используя ассемблер:

$ mxm2c-as hello.s hello

Отлично! Запустите виртуальную машину, передав полученный файл:

$ java downadow.iiixmish2.main.Iiixmish2 hello

Обзор[3][2]

Данная программа записывает строку str в видеопамять до тех пор, пока не встретится нулевой байт, после чего переходит к final и обновляет экран. Конец программы.

Инструкция JMP выполняет переход к адресу, который извлекается из заданного регистра. Существует также команда CALL, имеющая форму call регистр, адрес, где первый операнд — регистр, в который будет (если не 0) положен следующий после инструкции адрес (то есть PC+1), а второй — адрес, на который надо перейти (например, <label>).

Регистры

Как уже было сказано ранее, iiixmish2 имеет 44 пользовательских регистров (п. реги́стры).

Избегайте использования п. регистров 2, 3, 4 и 5, т. к. они могут использоваться некоторыми командами.[2]

Операции[3][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

mov2

mov2 — синоним mov. Не используйте его в новом коде.

Сдвиг

Следующий код выполняет операцию вида UR20 << UR19 (сдвиг битов влево) и сохраняет результат в UR8:

lshift UR20 UR19, UR8

UR8 = UR20 >> UR19:

rshift UR20 UR19, UR8

Для побитовых XOR, OR и AND, используйте одноимённые инструкции.

Получение времени

Команда time копирует в заданный регистр кол-во миллисекунд, приблизительно начиная от запуска процессора. Принимает один аргумент. trst сбрасывает время.

Комментарии

Коммента́рий — это текст в коде программы, который не влияют на её работу, но, как правило, помогает лучше понять её. В Makexm2c комментарии могут быть разных видов.[3]

Метки[3]

Ме́тки — в Makexm2c — это неотъемлемая часть языка. Обращение к метке вставляет на месте обращения адрес, по которому располагается эта метка в двоичной форме программы. Пример:

метка:
    nop
    nop
    mov UR0, <метка>

Для обращения, название метки, заключённое в < и >, вставляется в нужное место в программе.

Именованные константы[3]

Для создания именованных констант используется директива .def, пример:

.def %CONST% "0"

создаст именованную константу «CONST» со значением «0».

Обращение к именованным константам отличается от обращения к меткам лишь тем, что название заключается в %, а не < и >.

Задание

Потренируйтесь с пройденными командами.


В iiixmish2 есть команды для создания условных переходов. Рассмотрим, как использовать их в Makexm2c.

Равно

В iiixmish2 нет инструкций вроде BRz, BRn и т. д., ветвление реализуется посредством команд IFA, IFB, IFC и IFD. Для создания перехода вроде «если значение п. регистра А равно значению регистра Б, то выполнить переход на <значение п. регистра В>», воспользуйтесь следующей конструкцией:

if АДРЕС0 == АДРЕС1, АДРЕС2
Название Описание
АДРЕС0 адрес первого п. регистра для сравнения
АДРЕС1 адрес второго п. регистра для сравнения
АДРЕС2 адрес п. регистра, на значение которого нужно перейти


Ясно? Идём дальше.

Неравно

if АДРЕС0 != АДРЕС1, АДРЕС2

Больше

if АДРЕС0 > АДРЕС1, АДРЕС2

Меньше

if АДРЕС0 < АДРЕС1, АДРЕС2

Видеопамять

Как уже говорилось во введении, iiixmish2 имеет 2000 ячеек видеопамяти.

Почти все ячейки видеопамяти могут отображаться на экране. Последние две ячейки, — 1998-ая и 1999-ая, — хранят параметр цвета для фона и параметр цвета для отображаемых ячеек видеопамяти. Возможные цвета[2]:

Значение Цвет
1 белый
2 зелёный
3 голубой или синий
4 тёмно-зелёный
5 серый
6 красный
7 жёлтый
иное чёрный


Пример изменения цвета отображаемых ячеек видеопамяти на жёлтый:

mov UR0, 7
vsv UR0, 1999

Загрузка и сохранение[3][2]

Для загрузки значения из видеопамяти в п. регистр, используйте команду vld. Её аргументы:

Синтаксис Описание
ЦЦЦЦ адрес ячейки видеопамяти для загрузки
ЧИСЛО адрес п. регистра-приёмника

Пример использования:

vld 0001, UR8


Для сохранения значения п. регистра в ячейку видеопамяти, используйте vsv. Аргументы:

Синтаксис Описание
ЧИСЛО адрес п. регистра для сохранения
ЦЦЦЦ адрес нужной ячейки видеопамяти

Пример использования:

vsv UR0, 0063

Вы также можете вписывать адрес п. регистра вместо ЦЦЦЦ в аргументах этих команд (такое поддерживается в Makexm2c). Так, vsv UR0, UR16 сохранит содержимое п. регистра 0 в яч. видеопамяти, адрес которой находится в регистре 16.

Вы можете печатать разными цветами! Для этого, измените ячейку видеопамяти, на месте которой будет изменение цвета последующих, на 255 плюс нужное значение цвета.[2]

Задание

Напишите программу, которая складывает два числа и выводит результат на экран.

Память

Программы iiixmish2 загружаются в его па́мять (насколько это возможно).[2] Ограничения кода вне 0-65535:

  1. нельзя читать/прыгать/писать в 0-65535
  2. нельзя читать 9999872-9999999
  3. нельзя изменять 9999000-9999099
  4. действие инструкции OFF равно переходу к 32768

Загрузка и сохранение[3][2]

Команда ild предназначена для загрузки значений из памяти в п. регистры. Аргументы:

Синтаксис Описание
ЦЦЦЦЦЦЦ адрес ячейки памяти для загрузки
ЧИСЛО адрес п. регистра-приёмника.

Пример использования:

ild 6001900, UR0

Для сохранения значения п. регистра в память, используйте isv. Аргументы:

Синтаксис Описание
ЧИСЛО адрес п. регистра для сохранения
ЦЦЦЦЦЦЦ адрес нужной ячейки памяти

Пример использования:

isv UR10, 0999999


Вы можете вписывать адрес п. регистра вместо ЦЦЦЦЦЦЦ в аргументах этих команд.

Примеры программ

Ниже представлен пример программы, в которой пользователь может вводить данные. То, что от символа «;» до конца строки будет комментарием.

mov UR28, <loop>
; указатель вывода
mov UR27, 0
; ноль
mov UR0, 0

loop:
    ; эта команда ничего не делает,
    ; её выполнение может занимать
    ; до миллисекунды
    nop
    ; проверка клавиши
    if UR1 == UR0, UR28
    ; сохраняем символ
    vsv UR1, UR27
    ; увеличиваем указатель
    inc UR27
    ; сбрасываем регистр клавиатуры
    mov UR1, 0
    ; обновляем экран
    updd
    
    ; продолжение
    jmp UR28

Вариант «hello, world» с функциями:

.def %R_OUTPUT% "UR42"
.def %R_RETURN% "UR43"

mov %R_OUTPUT%, 0
mov UR0, <main>
jmp UR0

string:
    .skip 16
    .ascii <string> "hello, world"

main:
    mov UR0, <string>
    call %R_RETURN%, <puts>
    
    call %R_RETURN%, <halt>

puts:
    ild UR0, UR8
    mov UR10, 0
    mov UR11, <_puts_final>
    if UR8 == UR10, UR11
    vsv UR8, %R_OUTPUT%
    inc UR0
    inc %R_OUTPUT%
    mov UR11, <puts>
    jmp UR11
_puts_final:
    updd
    jmp %R_RETURN%

halt:
    mov UR0, <halt>
    jmp UR0

Ещё директивы

.ascii <mem0> "hello world" приказывает ассемблеру записать строку «hello world», начиная с яч. <mem0> (адрес метки mem0). .skip N пропускает N байтов, это похоже на N nop'ов. .byte ЧИСЛО вставит десятичное ЧИСЛО. .orig 1000 выполнит переход к ячейке 1000 (следующий после этого код будет записан, начиная с ячейки 1000).

Общение с другими компьютерами

Iiixmish2 и другие компьютеры (включая ЭВМ, на котором выполняется iiixmish2) могут «общаться» через порты ввода/вывода. Данные, которые передал компьютер, сохраняются в памяти iiixmish2, начиная с адреса 9999872. Чтобы ответить, запишите краткий ответ, начиная с адреса 9999000.

Ещё команды[3]

Это последний раздел изучения. В нём описываются команды off и vrst.

off

Если off выполняется в коде 0-65535, то он завершает работу iiixmish2; иначе выполняется переход к 32768.

vrst

vrst заменяет значения почти всех ячеек видеопамяти на неотображаемое (0), предназначение — убрать текст с экрана.

Примечания