MIPS: Эквивалент ла инструкции без использования псевдо кодов - PullRequest
3 голосов
/ 08 октября 2009

В справочнике говорится, что псевдокод для la (адрес загрузки) переведен на:

Pseudo : la $1, Label   

lui $1, Label[31:16]
ori $1,$1, label[15:0]

но когда я пытаюсь собрать код в MARS, я получаю ошибку:

"Недопустимый языковой элемент: 16]

и если я уберу часть [31:16], я получу

«Метка»: операнд неправильного типа

Есть идеи?

Ответы [ 2 ]

5 голосов
/ 08 октября 2009

Это означает, что 16 старших разрядов метки установлены в $ 1. Затем 16 младших разрядов объединяются с 16 старшими разрядами.

Здесь вы можете найти описание инструкции lui. Он загружает 16 бит бит адреса метки в регистр и обнуляет 16 фунтов.

Таким образом, вы можете загрузить 32-битный адрес (в mips32) с помощью 32-битных инструкций.

Он никоим образом не предназначен, чтобы быть "реальным кодом". Часть [31:16] / [15: 0] недопустима в мипах и предназначена только для того, чтобы вы понимали движения битов.

Edit: В ответ на ваш комментарий вам нужно знать адрес, который вы хотите загрузить, используя инструкцию lui. Для этого вы можете использовать метку для указания нужного адреса. Например

.data 
my_var: .asciiz "This is a nul terminated string"

.text
        andi $a0,$a0,0x0000ffff
        lui $a0,my_var
        ori $a0,$a0,my_var
2 голосов
/ 20 декабря 2015

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

На самом деле, можно сказать, где вы хотите разместить свой сегмент данных (например, 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 хранится! Этот подход создает указатель в памяти. Я бы порекомендовал разместить указатели перед другими данными переменной длины, чтобы вы могли легко вычислить смещение указателей.

...