Граница двойного слова MIPS и указатель стека

В MIPS для хранения двойного значения (8 байт) указатель стека $sp уменьшается на 4:

addi    $sp, $sp, -4
s.d     $f10, 0($sp)

Для меня это не имеет смысла, так как в памяти занято 8 байтов, но указатель стека перемещается так, как будто он использует границу одного слова. Кажется, что для хранения двух двойников указатель стека должен быть уменьшен на 12, а не на 16, как ожидалось:

addi    $sp, $sp, -12
s.d     $f10, 0($sp)
s.d     $f12, 8($sp)

Почему происходит такое поведение? Затем это вызывает проблемы, если подпрограмма вызывается рекурсивно (первый раз выравнивается, второй - нет)

Изменить: я запускаю этот код с MARS 4.5. s.d $f10, 8($sp) переводится как

lui $1,0
addu $1,$1,$29
sdc1 $f10,8($1)

Указатель стека в это время не перемещается. Пошаговое выполнение выглядит так, как будто sdc1 одновременно помещает в стек и $f10, и $f11.


person qwr    schedule 16.04.2016    source источник
comment
Что/кто генерирует этот код (то есть, что/кто решает, насколько уменьшить указатель стека)? В MARS s.d является псевдоинструкцией. Возможно, просмотр расширения псевдоинструкции в контексте полной программы поможет ответить на ваш вопрос.   -  person Zack    schedule 17.04.2016
comment
@Zack Я обновил исходный пост.   -  person qwr    schedule 17.04.2016
comment
Я также думаю, что указатель стека должен быть уменьшен на 8, а не на 4. Что заставляет вас думать, что 8 — это неправильно?   -  person Zack    schedule 18.04.2016
comment
@Zack Единственная причина в том, что MARS выдает ошибку Runtime exception at 0x0040000c: address not aligned on doubleword boundary 0x7fffeff4 (для addi $sp, $sp, -8)   -  person qwr    schedule 18.04.2016


Ответы (1)


Проверьте, не установлено ли значение переменной $sp, не кратное 8. Если да, попробуйте следующее: andi $sp, $sp, 0xfffffff8. Это должно уменьшить $sp до следующего числа, кратного 8. Однако вам нужно позаботиться о том, чтобы вы могли правильно вернуть $sp к исходному значению.

person Zack    schedule 19.04.2016
comment
Я использую add $sp, $sp, -4 и add $sp, $sp, 4, что по сути эквивалентно. Меня больше интересует причина ошибки MARS. - person qwr; 29.04.2016
comment
MIPS требует, чтобы данные были выровнены. Это означает, что адреса слов данных должны быть кратны 4, а адреса данных двойных слов должны быть кратны 8. Предположим, что $sp инициализируется значением, кратным 8, затем вы вставляете целое число, а затем вставляете двойное слово с плавающей запятой. Второй толчок вызовет ошибку во время выполнения, потому что $sp больше не будет кратным 8. andi выше "округляется в меньшую сторону"; это не вычитается. - person Zack; 02.05.2016