2016-12-18 10 views
1

У меня есть задание, в котором я должен объяснить некоторые вещи, о следующем коде MIPS Ассамблеи:MIPS Ассамблея луй 0x1001

.data 
x: .word 4711 
y: .word 10 
z: .word 0x0A91 
e: .word 0 

.text 
.globl main 
main: 
lw $2, x 
lw $3, y 
lw $4, z 
add $2, $2, $3 
sub $3, $2, $4 
sw $3, e 
li $2, 10 
syscall 

Первая инструкция lw $2, x разделяется на две инструкции при сборке. Инструкции: lui $1, 0x00001001, а затем lw $2, 0x00000000($1). Я понимаю, что lui перемещает шестнадцатеричное значение 1001 в верхнюю часть регистра, а значение, хранящееся в $ 1 в этой точке, равно 0x10010000, но я не понимаю, откуда приходит 1001 и что означает вторая инструкция. Я бы действительно воспринял любую помощь по этому вопросу. Я использую MARS для сборки и запуска этой программы.

+0

'0x10010000' случается адрес' x'. – Jester

+0

О, ОК. – Max

ответ

2

Инструкции MIPS имеют длину 32 бита, и поэтому адреса используются программой.
Это означает, что инструкция lw не может указать полный 32-разрядный адрес как немедленный. Проще говоря, инструкция lw $t, var недействительна (ожидайте для очень немногих случаев).

В самом деле, его кодирование

lw $t, offset($s) 
1000 11ss ssst tttt iiii iiii iiii iiii 

Где I биты показывают, что только 16 битов используются для указания адреса (и о том, что базовый регистр всегда должен быть указан, в конечном счете $zero регистр может использоваться).

Так ассемблер делает этот трюк: всякий раз, когда вы используете lw $t, var он собирает эту инструкцию в два инструкций, один, что нагрузить верхние 16 бит адреса в $at и lw, которые используют $at в качестве базового регистра с более низкие 16 бит адреса в качестве смещения.

lui $at, ADDR_H   #ADDR_H is ADDR >> 16 
lw $t, ADDR_L($at)   #ADDR_L is ADDR & 0xffff 

Заметим, что так как lw считывает из $at + ADDR_L конечный адрес, используемый в ADDR_H < < 16 + ADDR_L = ADDR. Как и ожидалось.

Существует тонкость, указал Mike Spivey (ему большое спасибо), смотрите ниже

Этот вид инструкций, которые не отображаются непосредственно в ISA, называются псевдо- инструкция. Регистр $at зарезервирован для ассемблера точно для их реализации.


В MARS можно отключить инструкции псевдо отключив Настройки> Разрешения продлен (псевдо) инструкции и формат.
Хотя программирование без псевдо-инструкций будет очень раздражать довольно быстро, стоит хотя бы раз сделать это, чтобы полностью понять архитектуру MIPS.


Mike Spivey правильно отметил, что 16-битовое смещение является непосредственным входа продлен перед добавлением в базовый регистр.
Это требует коррекции значения, которое я назвал ADDR_H, в случае, если ADDR_L оказывается отрицательным при интерпретации номера дополнения 16-разрядного двоичного кода.
Если это правда, ADDR_H должен быть увеличен.
Общая формула для ADDR_H может быть исправлена, чтобы ADDR_H = ADDR >> 16 + ADDR[15] где ADDR[15] обозначает значение бита 15 из ADDR (который является знаковым битом ADDR_L.

+0

Одна небольшая ошибка: смещение в инструкции lw подписано, поэтому неправильно вычислять ADDR_H с сдвигом в одиночку. Если ADDR_L оказывается отрицательным, то ADDR_H необходимо увеличить на 1., чтобы компенсировать. после этого, конечно. –

+0

@MikeSpivey Большое спасибо! Это очень хороший момент! Я считаю, что достаточно добавить бит15 исходного адреса ADDR_H, чтобы исправить это. Я редактирую ответ. –

+0

Когда написав MIPS-ассемблер, я положил короткий ADDR_L = (короткий) ADDR; короткий ADDR_H = (ADDR - ADDR_L) >> 16; assert (ADDR == ADDR_H << 16 + ADDR_L); , что составляет то же самое. –