Заниматься математикой
Все вычисления происходят между регистрами. Арифметическая инструкция называет сначала приёмник, а затем два источника, которые она читает: означает dest = src1 + src2.
add помещает t0 + t1 в t2.
t0 и t1, всегда в этом порядке. Они входят в одну и ту же форму независимо от выполняемой операции: сложение, вычитание, умножение, деление или остаток. Входят два значения, происходит одна операция, и одно значение выходит в t2 справа. называет t2 первым, потому что именно туда попадает результат, что соответствует единственному правилу порядка, которому следует каждая арифметическая инструкция в этом уроке.Сложение и вычитание
берёт числа, хранящиеся в двух регистрах, и записывает их сумму в третий. делает то же самое для вычитания: вычисляет t0 - t1. Обе инструкции читают только из регистров.
add t2, t0, t1 # t2 = t0 + t1sub t2, t0, t1 # t2 = t0 - t1
Одна вещь, которую стоит знать: регистр хранит только 32 бита, поэтому существует потолок. Если результат слишком велик, чтобы поместиться, ошибка не возникает. Значение тихо заворачивается к очень малым числам, и выполнение продолжается. Обычные значения не достигнут этого предела, но о потолке стоит знать.
Чтобы использовать фиксированное число вместо второго регистра, добавьте букву i, которая означает непосредственный: прибавляет константу 1. Инструкции subi нет, поэтому чтобы вычесть константу, прибавляют отрицательную: .
Умножение и деление
умножает два регистра. делит их как целые числа и отбрасывает дробную часть, поэтому 7 / 2 даёт 3. даёт остаток, поэтому 7 % 2 даёт 1. Деление никогда не вызывает сбоя. Деление на ноль возвращает -1.
mul t2, t0, t1 # t2 = t0 * t1div t2, t0, t1 # t2 = t0 / t1 (целое)rem t2, t0, t1 # t2 = t0 % t1 (остаток)
Сборка
li t0, 7li t1, 5add t1, t0, t1 # t1 = 7 + 5 = 12mv a0, t1 # сервис вывода читает a0li a7, 1ecallli a7, 10ecall
загружает 7 в t0. загружает 5 в t1. складывает их и записывает 12 в t1. копирует результат в a0, потому что служба печати всегда читает своё значение из a0. Затем выбирает службу печати целого числа, и запускает её. Наконец, и завершают программу.
Бонус: умножение с помощью сдвигов
Когда множитель является степенью двойки, существует более быстрый метод, чем . (логический сдвиг влево) перемещает биты регистра влево, и каждая позиция сдвига удваивает значение: сдвиньте на 1, чтобы умножить на 2, на 2 — для 4, на 3 — для 8. Сдвиг стоит меньше, чем умножение, поэтому компиляторы часто его используют.
li t0, 5 # начать с 5# сдвиг влево на 3 бита (5 * 2^3 = 5 * 8)sll a0, t0, 3 # a0 = 40li a7, 1 # вывести целое числоecallli a7, 10ecall
помещает 5 в t0. сдвигает его биты на три позиции влево. Каждая позиция удваивает значение, поэтому 5 удваивается три раза (5, 10, 20, 40), давая 40 в a0. Остальное следует шаблону печати из предыдущего. Попробуйте изменить 3 на 1 или 2 и предскажите результат, прежде чем запускать.
5 сдвинуто влево на 0 бит — результат остаётся 5.
