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 |