Лекция 2

Предполагаем, что с двоичной и шестнадцатеричной системами счисления все знакомы.

Сегодня поговорим уже собственно про архитектуру MIPS.

Идея MIPS - эффективная реализация в железе плюс система команд, достаточная для написания систем общего назначения.

Эти же люди придумали RISC (?)

Команды должны были быть максимально просты и эффективны, всё остальное программист напишет сам, особенно если: 1. он знает, на каком железе работает; 2 он знает, какие алгоритмы для его задач подходят больше.

В архитектуре самого процессора отсутствуют вычислительно сложные операции (например, в MIPS-32 любая команда занимает одно машинное слово, 4 байта)

В отличие от архитектур из начала 80-ых, где экономили всё-всё-всё, в MIPS регистровой памяти должно (по идее) хватать на всё, что потребуется (в разумных пределах)

Сразу 32 регистра общего назначения (РОН) - это никак не влияет на быстродействие, но делает вычисления удобнее

Общее свойство RISC-архитектур: память считается медленным устройством (и это правда так), и чтобы результирующий код получился эффективным, команды взаимодействия с памятью ограничиваются командами выгрузки/загрузки в память, а все вычислительные операции проводятся на регистрах.

С моей точки зрения, особенность MIPS - не только в аппаратной специфике, но и в том, на кого она ориентирована (но это неточно).

Поясняю: Архитектура MIPS принципиально трёхоперандная (используется ещё термин "трёхадресная", но, строго говоря, он не совсем корректен). При этом с учётом того, что вычислительные операции не используют память, мы ничего не теряем

Память команд и память данных разделены (отсылка к Гарвардской архитектуре?). Это можно рассматривать как нарушение одного из принципов архитектуры фон Неймана, однако программисты избегают самомодифицирующийся код многие десятилетия, так что это не важно.

Сама система команд MIPS и некоторые её особенности оптимизированы под конвейеризацию.

В практике программирования на MIPS используется термин псевдоинструкция - инструкция, обозначающая некоторую полезную операцию, но с точки зрения реализации являющаяся некоторым "хаком"

В MIPS есть регистр ноль, в котором всегда лежит ноль :)

Таким образом, можно заключить, что создатели MIPS считали, что язык MIPS-ассемблера должен быть удобен, в первую очередь, для написания людьми

Насколько удобен для чтения код для MIPS-ассемблера, настолько же неудобен для чтения полученный машинный код

В MIPS не используются флаги (регистра флагов даже нет, атомарные операции и так хорошо работают, и счёт производится быстрее)

32-разрядное машинное слово

Т.к. размер инструкций фиксирован, мы всегда знаем, в каких битах что лежит

См. слайд с описанием полей

Даже одного машинного слова из 32 битов на команду - это много

Ни одно из функциональных полей машинного слова не кратно 4

R-тип команд - команды, работающие с регистрами

Отдельный тип команд - Immediate, где Immediate - это некое число, которое играет роль... числа

J-тип команд

В поле target подразумевается наличие ещё двух битов в конце (которые всегда имеют значение ноль, ведь адресовать менее 4 байт у нас не выйдет)

См. слайд с арифметическими командами

Знаковые и беззнаковые операции отличаются вызовом исключения при переполнении (что довольно неожиданно): в простой операции сложения может возникнуть исключение, а в беззнаковой - нет

Т.е. мы не работаем с какими-то специальными данными, знаковыми или беззнаковыми; просто есть два типа сложения, учитывающие знак или не учитывающие (сделали ошибку в последнем - сами виноваты)

В ассемблере MIPS общий вид команды - куда, откуда, что

Проблемы с умножением: 1. операция долгая 2. в знаковом умножении знать знак числа важно 3. переполнение - для этого в MIPS придумали регистры HI и LO (обратите внимание, что операция умножения здесь - двухоперандная, третий операнд не используется)

Вы даже сами определиться, что вам дальше делать с полученными числами

Есть отдельные команды переноса полученных значений из регистров HI и LO в rd - MFHI (move from HI), MFLO (move from LO)

В MIPS, несмотря на отсутствие регистра флагов, иногда всё-таки нужно проводить некоторые условные операции

ПРОВЕРИТЬ ИНФОРМАЦИЮ ПРО КОМАНДУ MOVN Всё-таки в ней destination на втором месте

Есть команда ИЛИ-НЕ (см. слайды с командами)

Я сейчас рассказываю про все эти команды, чтобы вы примерно представляли, с чем мы примерно будем работать; всё равно в процессе выполнения домашних заданий с этим придётся разбираться более подробно и детально, а в MARS-е есть подробный help со всеми командами

В MARS-е обязательно сохраняйте код, иначе кнопка запуска программы будет работать некорректно

Область кода всегда начинается с адреса 0x00400000

В лекции см. пример разбора команды в машинном коде

По моему мнению, разработчики MIPS не предполагали, что бинарный код будут читать нормальные люди

LB rt, offset(rs) - в такой команде используется косвенная адресация (опять же, см. слайды)

Относительно команд перехода:

J target, JR (jump с return-ом)

Работа с памятью возможна со словами, с полусловами, с байтами

Адреса во всех случаях должны быть кратными (выравнивание)

В MIPS нельзя положить что-либо 4-байтное по не кратному 4 адресу

Одни из немногих нарушений принципа регистров общего использования - r0 и rd

Команды условного перехода имеют уже другой вид (BEQ, BNE, BLEZ,..)

Обратите внимание, среди этих команд нет инструкций сравнения двух регистров на больше-меньше

Но есть сравнение на равенство и сравнение с нулём

Операция сравнения двух значений - это 2 операции

Поскольку у нас АЛУ одно, мы не можем за одно действие сравнить два числа (сначала нужно одно из другого вычесть, потом сравнить с нулём)

Расскажу всё-таки про псевдоинструкции

См. в лекции пример программы (некоторые формы операции li - load immediate - псевдоинструкции)

Поговорим о том, как писать домашние задания MARS нас обеспечивает очень простыми системными вызовами

Будем решать один тип задач - ввели числа, обработали, вывели

Для ввода числа в регистр v0 нужно положить число 5 (это номер системного вызова) и произвести системный вызов:

li $v0 5 syscall

Для вывода числа - в a0 положить число, в v0 положить 1, произвести системный вызов

Пример:

li $a0 42 li $v0 1 syscall

Для завершения программы:

li $v0 10 syscall

LecturesCMC/ArchitectureAssembler2019/02_Mips_Architecture/conspect (last edited 2019-02-22 16:37:38 by RomanKrivonogov)