Перейти к содержанию

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

завершено на 100%
Материал из Викиучебника — открытых книг для открытого мира
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

Данная программа записывает строку 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 — синоним 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 выполняется в коде 0-65535, то он завершает работу iiixmish2; иначе выполняется переход к 32768.

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

Примечания

[править]