Материал: Архитектура и программирование MIPS-процессоров. Разинкин К.А

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

0x00405000

beq $t9, $s7, back

(d)

 

0x00403000

jal func

...

...

3.2.24. Рассмотрим следующий фрагмент кода на языке ассемблера MIPS. Числа слева от каждой инструкции указывают ее адрес:

0x00400028

 

add

$a0, $a1, $0

0x0040002C

 

jal

f2

0x00400030

f1:

jr

$ra

0x00400034

f2:

sw

$s0,0($s2)

0x00400038

 

bne

$a0,$0, else

0x0040003C

 

j

f1

0x00400040

else:

addi

$a0, $a0, −1

0x00400044

 

j

f2

a)Транслируйте последовательность инструкций в машинный код в шестнадцатеричном формате.

b)Сделайте список режимов адресации, которые были использованы для каждой строки кода.

3.2.25.Рассмотрим следующий фрагмент кода на C:

//C code

void setArray(int num) { int i;

int array[10];

for (i = 0; i < 10; i = i + 1) { array[i] = compare(num, i);

}

}

int compare(int a, int b) { if (sub(a, b) >= 0)

return 1; else

return 0;

}

int sub(int a, int b) { return a − b;

}

116

a)Перепишите этот фрагмент кода на языке ассемблера MIPS. Используйте регистр $s0 для хранения переменной i. Следите за тем, чтобы правильно работать с указателем стека. Массив хранится в стеке функции setArray.

b)Предположим, что первой вызванной функцией будет setArray. Нарисуйте состояние стека перед вызовом setArray и во время каждого последующего вызова. Укажите имена регистров и переменных, хранящихся в стеке. Отметьте расположение $sp и каждого кадра стека.

c)Как бы работал ваш код, если бы вы забыли сохранить в стеке регистр $ra?

3.2.26.Рассмотрим следующий фрагмент кода на C:

// C code

int f(int n, int k) { int b;

b = k + 2;

if (n == 0) b = 10;

else b = b + (n * n) + f(n − 1, k + 1); return b * k;

}

a)Транслируйте функцию f на язык ассемблера MIPS. Обратите особое внимание на правильность сохранения и восстановления регистров между вызовами функций, а также на использование конвенций MIPS по сохранению регистров. Тщательно комментируйте ваш код. Вы можете использовать инструкцию mul. Функция начинается с адреса 0x00400100. Храните локальную переменную b в регистре $s0.

b)Пошагово выполните функцию из пункта (a) для случая f(2, 4). Изобразите стек, как на рис. 2.16 (c). Подпишите имена и значения регистров, хранящихся в каждом слове стека. Проследите за значением указателя стека ($sp). Четко обозначьте каждый кадр стека. Для вас также может быть полезно отследить значения в $a0, $a1, $v0 и $s0 в процессе выполнения программы. Предположим, что при вызове f значение $s0 =

117

0xABCD, а $ra = 0x400004. Каким будет конечный результат в регистре $v0?

3.2.27.Каков диапазон адресов, по которым инструкции ветвления, такие как beq и bne, могут выполнять переходы в MIPS? Дайте ответ в виде количества инструкций относительно адреса инструкции ветвления.

3.2.28. Ответы на приведенные ниже вопросы позволят вам лучше понять работу инструкции безусловного перехода, j. Дайте ответы в виде количества инструкций относительно адреса инструкции безусловного перехода.

a)Как далеко вперед (то есть по направлению к большим адресам) может перейти команда безусловного перехода (j) в наихудшем случае?

Наихудший случай – это когда переход не может быть осуществлен далеко. Объясните словами, используя по необходимости примеры.

b)Как далеко вперед может перейти команда безусловного перехода (j) в наилучшем случае? Наилучший случай – это когда переход может быть осуществлен дальше всего. Поясните ответ.

c)Как далеко назад (то есть по направлению к меньшим адресам) может перейти команда безусловного перехода (j) в наихудшем случае? Поясните ответ.

d)Как далеко назад может перейти команда безусловного перехода (j) в наилучшем случае? Поясните ответ.

3.2.29.Объясните, почему выгодно иметь большое поле адреса (addr) в машинном формате команд безусловного перехода j и jal

3.2.30 Напишите код на языке ассемблера, который переходит к инструкции, отстоящей на 64 мегаинструкции от начала этого кода. Напомним, что 1 мегаинструкция = 220 инструкций = 1,048,576 инструкций. Предположим, что ваш код начинается с адреса 0x00400000. Используйте минимальное количество инструкций.

118

3.2.31. Напишите функцию на языке высокого уровня, которая берет массив 32разрядных целых чисел из 10 элементов, использующих прямой порядок следования байтов (от младшего к старшему, little-endian) и преобразует его в формат с обратным порядком (от старшего к младшего, big-endian).

Перепишите код на языке ассемблера MIPS. Прокомментируйте весь ваш код и используйте минимальное количество инструкций.

3.2.32. Рассмотрим две строки: string1 и string2.

a)Напишите код на языке высокого уровня для функции под названием concat, которая соединяет их (склеивает их вместе): void concat(char string1[], char string2[], char stringconcat[]). Заметьте, что эта функция не возвращает значения (т.е. тип возвращаемого значения равен void). Результат объединения string1 и string2 помещается в строку в stringconcat. Предполагается, что массив символов stringconcat является достаточно большим, чтобы вместить результат.

b)Перепишите код из части (a) на языке ассемблера

MIPS.

3.2.33. Напишите программу на ассемблере MIPS, которая складывает два положительных числа с плавающей точкой одинарной точности, которые хранятся в регистрах $s0 и $s1. Не используйте специальные инструкции для работы с плавающей точкой. В этом упражнении вам не нужно беспокоиться о кодах значений, зарезервированных для специальных целей (например, 0, NaN и т.д.), а также о возможных переполнениях или потере точности. Используйте симулятор SPIM для тестирования кода. Вам нужно будет вручную установить значения

$s0 и $s1, чтобы протестировать код.

Продемонстрируйте, что ваш код работает надежно. 3.2.34. Покажите, как приведенная ниже программа

MIPS загружается и выполняется в памяти.

119

#

MIPS assembly code

main:

 

 

addi

$sp, $sp, −4

 

sw

$ra, 0($sp)

 

lw

$a0, x

 

lw

$a1, y

jal

diff

 

 

lw

$ra, 0($sp)

 

addi

$sp, $sp, 4

jr

$ra

 

diff:

 

 

 

sub

$v0, $a0, $a1

 

jr

$ra

a)Сначала отметьте рядом с каждой инструкцией ее адрес.

b)Нарисуйте таблицы символов для меток и их адресов.

c)Сконвертируйте все инструкции в машинный код.

d)Укажите размер сегментов данных (data) и кода (text) в байтах.

e)Нарисуйте карту памяти и укажите, где хранятся данные и команды.

3.2.35.Повторите предыдущее упражнение для следующего кода

# MIPS assembly code

main:

 

addi

$sp, $sp, −4

sw

$ra, 0($sp)

addi

$t0, $0, 15

sw

$t0, a

addi

$a1, $0, 27

sw

$a1, b

lw

$a0, a

jal greater

lw

$ra, 0($sp)

addi

$sp, $sp, 4

 

120

Источник: https://studfile.net/preview/16568788/