Это действительно хороший вопрос, где я пришел к возможному решению. Ответ выше не работает безоговорочно.
На самом деле, можно сказать, где вы хотите разместить свой сегмент данных (например, SPIM позволяет вам это сделать). Директива .data
принимает один необязательный аргумент - 32-битный адрес, где должен находиться этот сегмент данных. Таким образом пишутся обработчики исключений (только с использованием .kdata
вместо .data
).
Пример:
.data 0x10001000 #remember this location
.align 0
.asciiz "MIPS IS GREAT!" #this is at offset 0
.text
.align 2
.globl main
main: #let's assume we've got no arguments
addiu $sp, $sp, -24 #subroutine prolog
sw $ra, 16($sp)
sw $fp, 10($sp)
addiu $fp, $sp, 20
ori $v0, $0, 4
lui $a0, 0x1000 #sole argument must be str pointer
ori $a0, $a0, 0x1000
syscall #print STR out on console
lw $ra, 16($sp) #subroutine epilog
lw $fp, 10($sp)
addiu $sp, $sp, 24
jal
На самом деле я не уверен, является ли это лучшим решением, но это единственное решение, о котором я могу подумать (даже без использования виртуальных режимов адресации, например, меток для загрузки или сохранения инструкции), и эта идея должна работать (будь то мой код пример работает, я не знаю, я его не проверял).
EDIT:
Я только что поиграл и обнаружил действительно удивительный трюк, который позволяет нам также загружать метку в регистры без каких-либо псевдоинструкций и с естественным режимом адресации. Мой пример:
.data 0x10001000
.word LABEL
LABEL: .asciiz "Get LABEL to print this C string."
.text
.align 2
.globl main
#test if it loads LABEL
main:
lui $4, 0x1000
ori $4, $4, 0x1000
lw $4, 0($4)
ori $2, $0, 4
syscall
В SPIM он отлично собирается! Посмотрите на память на 0x10001000 показывает, 0x10001004 хранится! Этот подход создает указатель в памяти. Я бы порекомендовал разместить указатели перед другими данными переменной длины, чтобы вы могли легко вычислить смещение указателей.