
Команды типа r-type (register type)
Команды типа R-type имеют 3 операнда, все операнды - адреса регистров, 2 регистра-источника, 1 регистр - назначение.
Рассмотрим 2 команды этого типа – add и sub.
Команда add
(add - сложить) очевидно складывает значения 2х регистров и кладет результат в 3й регистр.
Синтаксис на ассемблере:
add rd, rs, rt
rd, rs, rt - адреса (имена) регистров - команда add должна взять значения из регистров rs и rt, вычислить сумму rs+rt и записать результат в регистр rd.
например:
add $s0, $s1, $s2
на практике должно быть выполнено как $s0=$s1+$s2 - вычислить сумму значений, хранящихся в регистрах $s1 и $s2, и записать результат в регистр $s0. Команда sub
(subtract - вычесть) очевидно вычисляет разность значений 2х регистров и кладет результат в 3й регистр. синтаксис на ассемблере: sub rd, rs, rt rd, rs, rt - адреса (имена) регистров - команда sub должна взять значения из регистров rs и rt, вычислить разность rs-rt и записать результат в регистр rd например:
sub $s0, $s1, $s2
на практике должно быть выполнено как $s0=$s1-$s2 - вычислить разность значений регистров $s1 и $s2 и записать результат в регистр $s0.
Теперь посмотрим, как они выглядят в машинном коде
На всякий случай еще раз вспомним, что в 32-битном процессоре на каждую команду отведено ровно 32 бита. Команды типа R-type разбиты на следующие поля по битам:
[ op (6 бит) ][ rs (5 бит) ][ rt (5 бит) ][ rd (5 бит) ][ shamt (5 бит) ][ funct (6 бит) ]
(проверяем, что в сумме получаем 32 бита: 6+5+5+5+5+6=32). op+funct=операция op (opcode) = 0 для всех операций R-type funct (function): для add=32, для sub=34
rs, rt, rd - операнды - адреса регистров ('r' везде от register)
rs, rt - источник1, источник2 (обозначение выбрано как s - source, а 't' просто идет в алфавите после 's')
rd - назначение (destination)
shamt - сдвиг (ammount of shift) = 0 для всех операций R-type
Команды типа I-type (immediate type)
Команды типа I-type в отличие от команд типа R-type умеют работать с числовыми константами (immediates - надо понимать что-то типа "незамедлительные" значения, т.е. их не нужно ниоткуда получать), которые встроены прямо в код команды.
Из нашего списка к таковым относятся: lw, sw, addi, beq.
Команда lw (load word - загрузить слово) загружает значение из памяти данных в регистр. синтаксис на ассемблере: lw rt, imm (rs) rt - адрес регистра-назначения imm - константа - адрес загружаемого значения в памяти данных rs - адрес регистра, содержащего значение сдвига для адреса загрузки например:
lw $s0, 4 ($0)
сначала вычислит адрес загружаемого значения как значение imm + значение, содержащееся в регистре rs (4+0=4), затем считает значение по вычисленному адресу (4) из памяти данных и запишет его в регистр rt ($s0).
Команда sw (store word - сохранить слово) записывает (сохраняет) значение из регистра в память данных. синтаксис на ассемблере: sw rt, imm (rs) rt - адрес регистра-источника imm - константа - адрес сохранения значения в памяти данных rs - адрес регистра, содержащего значение сдвига для адреса сохранения например:
sw $s0, 4 ($0)
сначала вычислит адрес сохранения значения как значение imm + значение, содержащееся в регистре rs (4+0=4), затем считает значение из регистра rt ($s0) и сохранит его в память данных по вычисленному адресу (4). Команда addi (add immediate - сложить с константой) складывает значение регистра с константой и записывает результат в регистр.
синтаксис на ассемблере: addi rt, rs, imm rt - адрес регистра-назначения rs - адрес регистра, содержащего 1е складываемое значение imm - константа - 2е складываемое значение команда addi должна взять значения из регистра rs, вычислить сумму rs+imm и записать результат в регистр rt. например:
addi $s0, $s1, 4
на практике должно быть выполнено как $s0=$s1+4 - вычислить сумму значения, хранящегося в регистре $s1 со значением константы 4, и записать результат в регистр $s0.
Команда beq (branch if equal - ответвиться, если равно) осуществляет условный переход - перевод счетчика программы в указанное место при выполнении определенного условия.
В обычной ситуации процессор выполняет программу строка за строкой. Этот механизм реализован при помощи счетчика программы (program counter - pc) - на каждый логический такт процессор выбирает из памяти инструкций команду, индекс которой хранит счетчик программы, после ее выполнения счетчик программы увеличивается на одну команду так, что на следующий такт процессор выберет для выполнения команду, которая в памяти инструкций следует за текущей, и так может продолжаться до тех пор, пока не закончится память инструкций.
Команды перехода (в данном случае условного) позволяют нарушить последовательный ход программы и сделать так, чтобы на следующий такт процессор начал выполнять команду не следующую за текущей, а перенести выполнение в указанную точку памяти инструкций - для этого достаточно установить нужное значение в счетчик программы (pc).
При помощи команды условного перехода beq можно организовывать циклы и блоки проверки условий.
синтаксис на ассемблере:
beq rs, rt, imm
rs, rt - адреса регистров, значения которых сравнивает команда
imm - адрес перехода относительно адреса текущей инструкции (в ассемблерной программе задается при помощи специальных меток)
Адрес перехода задается при помощи специальных меток - символьных имен, которые можно назначить на любую строку в ассемблерной программе - транслятор в машинный код сам вычислит нужный адрес перехода. например:
label: addi $s0, $0, 4 beq $s0, $s1, label
сравнит значения регистров $s0 и $s1 и передаст управление инструкции, адрес которой в памяти инструкций равен адресу строки, помеченной меткой "label" (те в данном примере это одна строка выше), если значения равны; если значения не равны, то программа продолжит последовательное выполнение со следующей строчки.
Стоит обратить внимание на 2 вещи:
Замечание 1: Адрес инструкции - это индекс 1го байта инструкции в памяти инструкций - т.к. для 32-битной архитектуры каждая инструкция занимает ровно 4 байта (32 бита - слово), адреса перехода должны быть кратны 4м, другие адреса некорректны. Например 0 обозначает адрес 1й инструкции в программе, 4 - адрес 2й инструкции, 8 - адрес 3й инструкции и т.п. Значения адресов 1, 2, 3, 5, 6, 7 и т.п. указывают на середину инструкций, т.е. по сути не имеют смысла.
Замечание 2: Т.к. поле imm является частью 32-битной инструкции и само имеет длину 16 бит (для инструкции beq), длина прыжка ограничена максимальным значением, которое может уместиться в эти 16 бит (по 15 бит в каждую сторону - 16й бит на знак, определяющий направление перехода)
Теперь посмотрим, как они выглядят в машинном коде
Команды типа I-type разбиты на следующие поля по битам: [ op (6 бит) ][ rs (5 бит) ][ rt (5 бит) ][ imm (16 бит) ]
6+5+5+16=32
op - код операции: для lw=35, для sw=43, для addi=8, для beq=4
rs, rt - адреса регистров-операндов - смысловые роли могут быть разные для разных команд
imm (immediate) - значение операнда-константы
Команды типа J-type (jump type) Команда j (jump - прыжок) осуществляет безусловный переход - перевод счетчика программы в указанное место.
Принцип работы полностью аналогичен команде условного перехода beq, только переход осуществляется всегда и без всяких условий. Также диапазон перехода относительно текущего положения чуть больше, чем у команды beq, т.к. на адрес перехода внутри команды отведено 26 бит, а не 16.
синтаксис на ассемблере: j addr addr - адрес перехода относительно адреса текущей инструкции (в ассемблерной программе задается при помощи метки)
например:
label: addi $s0, $0, 4 j label
вернет управление на одну строку выше (в данном случае получим бесконечный цикл).
Машинный код
[ op (6 бит) ][ addr (26 бит) ]
6+26=32 op - код операции: для j=2
addr (address) - единственный операнд - константа - адрес перехода относительно текущего положения счетчика программы
Задание
1. Напишите таблицу всех регистров, включающую в себя:
- название регистра;
- порядковый номер;
- двоичный индекс;
- назначение.
2. Напишите код программы на ассемблере MIPS, которая загружает из памяти два числа, складывает их и результат помещает обратно в память.
3. Переведите эту программу в двоичный код. При переводе подробно распишите синтаксис команды каждого типа.
4. Выполните обратную задачу.
Какую программу выполняет следующий машинный код?
001000_00000_10000_0000000011100110
101011_00000_10000_0000000000000000
100011_00000_10001_0000000000000000
101011_00000_10001_1111000000000000
5. Выполните индивидуальное задание:
Вариант 1
Записать в регистр a значение 3, в регистр b 8. Сложить регистр a и регистр b, записать значение в регистр b. Прибавить к a 7. Сохранить в память значения регистров a и b.
Вариант 2
Записать в регистр a значение 4, в регистр b 9. Сложить регистр a и регистр b, записать значение в регистр b. Прибавить к a 3. Сохранить в память значения регистров a и b.
Вариант 3
Записать в регистр a значение 7, в регистр b 5. Сложить регистр a и регистр b, записать значение в регистр b. Прибавить к a 3. Сохранить в память значения регистров a и b.
Вариант 4
Записать в регистр a значение 6, в регистр b 3. Сложить регистр a и регистр b, записать значение в регистр b. Прибавить к a 4. Сохранить в память значения регистров a и b.
Вариант 5
Записать в регистр a значение 1, в регистр b 9. Сложить регистр a и регистр b, записать значение в регистр b. Прибавить к a 6. Сохранить в память значения регистров a и b.
Вариант 6
Записать в регистр a значение 2, в регистр b 8. Сложить регистр a и регистр b, записать значение в регистр b. Прибавить к a 3. Сохранить в память значения регистров a и b.
Вариант 7
Записать в регистр a значение 3, в регистр b 5. Сложить регистр a и регистр b, записать значение в регистр b. Прибавить к a 7. Сохранить в память значения регистров a и b.
Вариант 8
Записать в регистр a значение 3, в регистр b 8. Сложить регистр a и регистр b, записать значение в регистр b. Прибавить к a 2. Сохранить в память значения регистров a и b.
Вариант 9
Записать в регистр a значение 6, в регистр b 2. Сложить регистр a и регистр b, записать значение в регистр b. Вычесть из a 3. Сохранить в память значения регистров a и b.
Вариант 10
Записать в регистр a значение 9, в регистр b 1. Сложить регистр a и регистр b, записать значение в регистр a. Прибавить к a 6. Сохранить в память значения регистров a и b.
Контрольные вопросы
1. Чем определяется архитектура процессора? Нарисуйте структурную схему разрабатываемого процессора.
2. На какие группы можно разделить команды процессора? Чем они отличаются?
3. Перечислите какие команды может выполнять разрабатываемый процессор, отразите их синтаксис.
Содержание отчета
1 Название, цель работы
2 Задание (таблица, листинг созданных программ)
3 Письменные ответы на контрольные вопросы