Простой процессор

Простой процессор – модель 8-разрядного процессора, снабженного 256-байтным банком памяти. Основное назначение простого процессора – работа учебным стендом для наглядного объяснения принципов функционирования вычислительной техники, архитектуры процессоров, ассемблирования, выборки и исполнения команд. Неосновное назначение – причинение боли и страдания студентам-бездельникам и тем, кто наивно полагает, что в XXI веке программирование в машинных кодах больше никем и нигде не используется (спойлер: используется). Простой процессор – это предельно упрощенная и лишенная возможности микропрограммирования и ввода-вывода базовая ЭВМ.

Простой процессор имеет 4 регистра общего назначения (РОНа) – R0, R1, R2 и R3, регистр флагов RF и регистр-указатель команд RC. Простой процессор может непосредственно адресовать 256 байтов памяти, в которой размещаются команды и данные. Простой процессор оперирует 8-разрядными целыми числами со знаком (для представления отрицательных чисел используется дополнительный код). Числа могут быть записаны в десятичной системе счисления, шестнадцатеричной (с префиксом 0x, например, 0xAB) или двоичной (с префиксом 0b, например, 0b10101011).

Три малдших бита в регистре RF являются арифметическими флагами, остальные биты не используются. Бит Z (самый младший бит) устанавливается в 1 в случае, если результат последней арифметической команды равен 0, в противном случае бит Z сбрасывается в 0. Бит S (бит с порядковым номером 1) устанавливается в 1 в случае, если результат последней арифметической команды имеет в старшем бите единицу (то есть может рассматриваться как отрицательное число), в противном случае бит S сбрасывается в 0. Бит C (бит с порядковым номером 2) устанавливается в 1 в случае, если результат последней арифметической команды не поместился в разрядную сетку, и за её пределы был выполнен перенос, в противном случае бит C сбрасывается в 0. Проверить значения флагов в регистре RF можно с помощью команд условного перехода.

Регистр-указатель команд RC содержит адрес следующей исполняемой команды. Команды перехода фактически заносят в этот регистр адрес ячейки памяти, откуда нужно продолжить выборку команд. После "включения" простого процессора все регистры содержат нули и выполнение программы начинается с адреса 0.

Простой ассемблер для простого процессора

Простой ассемблер позволяет перейти от программирования в машинных кодах к символической записи команд, то есть, например, вместо записи команды в машинном коде 18 fe (или в двоичном представлении 00011000 11111110) записать её мнемоникой r2 <- @0xfe. Каждая команда может быть снабжена меткой (идентификатором, после которого стоит двоеточие, например, BEGIN:). Метка должна располагаться перед командой ассемблера в той же строке, что и команда.

Правильно: BEGIN: r2 <- @0xfe ; читаем текущее значение

Неправильно: BEGIN: r2 <- @0xfe ; читаем текущее значение

Простой ассемблер не различает верхний и нижний регистр символов, поэтому 0xFE и 0xfe – одно и то же число, r0 и R0 – один и тот же регистр, LOOP: и loop: – одна и та же метка.

Простым ассемблером поддерживаются однострочные комментарии, они начинаются с символа ; и продолжаются до конца строки. Простой ассемблер игнорирует пробельные символы и комментарии.

Система команд простого процессора

Мнемоника Двоичное представление Команда
Rdd <- Rss 0000ddss Пересылка данных из регистра в регистр
Rdd <- @aaaaaaaa 0001dd?? aaaaaaaa Пересылка данных из памяти в регистр
@aaaaaaaa <- Rss 0010??ss aaaaaaaa Пересылка данных из регистра в память
Rdd <-  nnnnnnnn 0011dd?? nnnnnnnn Запись в регистр константы
Rdd <- Rdd + Rss 0100ddss Сложение
Rdd <- Rdd − Rss 0101ddss Вычитание
Rdd <- Rdd * Rss 0110ddss Умножение
Rdd <- Rdd / Rss 0111ddss Деление (беззнаковое)
RF <- Rdd ~ Rss 1000ddss Сравнение
RC <- @aaaaaaaa (C) 1001???? aaaaaaaa Переход, если перенос
RC <- @aaaaaaaa (S) 1010???? aaaaaaaa Переход, если знак
RC <- @aaaaaaaa (Z) 1011???? aaaaaaaa Переход, если ноль
RC <- @aaaaaaaa 1100???? aaaaaaaa Безусловный переход
Rdd <- ? 1101dd?? Запись случайного числа в регистр
Rdd <- Rss++ 1110ddss Инкремент

Команды простого процессора могут быть поделены на несколько категорий:

Арифметические операции с данными возможны только в том случае, если данные находятся в регистрах. Все арифметические команды действуют по одному принципу: данные берутся из регистра-назначения (первый операнд, в команде обозначаемый как Rdd), затем – из регистра-источника (второй операнд, в командах обозначаемый как Rss), над ними производится действие, определяемое кодом операции, после чего результат записывается в регистр назначения и в регистре флагов устанавливаются соответствующие флаги. Команда сравнения, фактически работающая как команда вычитания, отличается от последней тем, что результат не сохраняется, но флаги в регистре флагов устанавливаются. Необходимо также отметить, что команда деления в простом процессоре работает с числами без знака.

Команды пересылки данных позволяют загрузить данные из памяти в РОНы для обработки и записать результаты из РОНов обратно в память. Команда инкремента Rdd <- Rss++, формально относящаяся к командам пересылки данных, похожа на копирование данных из регистра в регистр, но позволяет при этом записать в регистр назначения увеличенное на единицу значение регистра-источника.

В простом процессоре нет отдельной команды NOP (No OPeration), однако в таком качестве можно использовать запись из регистра в тот же регистр, например, r0 <- r0. Отдельной команды для останова процессора (HLT, HaLT) также не предусмотрено, для этого можно применять команду безусловного перехода на тот же адрес: HLT: rc <- @HLT ; стоп