MIPS - Являются ли символы, которые хранятся в байтах, такими же, как символы, которые не хранятся в байтах? - PullRequest
0 голосов
/ 30 августа 2018

Я новичок в MIPS, и мне просто интересно, я сохраняю символ пробела следующими способами:

li $t0, ' '
lb $t1, ' '

la $t2, myArray  # load array
sb $t0, 0($t2)   # myArray[0] = ' '

В этом случае $ t0 == $ t1? И действительна ли инструкция sb? Меня немного смущает, могу ли я использовать байты и целые числа (слова) взаимозаменяемо.

1 Ответ

0 голосов
/ 30 августа 2018

byte против word не является свободно взаимозаменяемым, потому что байт - это только 8 бит информации, а word - 32 бита информации (на платформе MIPS). Таким образом, byte может быть установлено на 256 различных возможных значений (2 8 комбинаций восьми значений 0/1 бита), а word может быть установлено на 256 4 различных возможных значения (шаблон из 32 бит).

Вам нужно четыре байта для хранения того же возможного количества информации, что и то, что вы можете уместить в одно слово (8 бит * 4 = 32 бита).

Но в зависимости от значений, которые вы обрабатываете, если вы можете гарантировать их диапазоны, вы можете предсказать, как будет вести себя код, преобразующий значения между байтом / полусловом / словом, выживут ли некоторые значения при таких преобразованиях без какого-либо ущерба, или это требует дополнительной проверки / обработки. Например, если ваши входные значения являются символами ASCII (из строки), то они являются только 7-разрядными (при интерпретации как целые числа со знаком, только значения от 0 до +127 определены в ASCII).

Так, например, li $t0, ' ' будет собираться как li $t0, 32 (потому что символ «пробел» кодируется в компьютере как значение 32) и потому что инструкция li принимает в качестве целого числа оперант сразу.

На самом деле «li» - это не настоящая инструкция MIPS, а вспомогательная псевдоинструкция, ассемблер преобразует ее в одну / две собственные инструкции для кодирования / составления желаемого непосредственного значения. Попробуйте, например, li $t0, ... со значениями +1, -1, +65000, -65000 и посмотрите в отладчике, как он собирается в разные встроенные инструкции, достигая желаемого эффекта «немедленной загрузки», например, для значения -65000 необходимо как минимум составить две родные инструкции.

Таким образом, вы технически загружаете 32-битное (слово) значение в $ t0 (даже если ' ' является единственным значением 32, которое легко помещается в байт).

Но, как вы знаете, вы загрузили ASCII "пробел" в t0, независимо от того, что t0 имеет ширину 32 бита, вы знаете, что достаточно сохранить только "байт" в памяти, если вы например, создание новой строки в буфере, и вы хотите поместить в нее символ пробела. Итак, sb $t0, 0($t2) правильно. Если бы у вас было большее значение в t0, старшие 24 бита игнорируются, и только 8 младших битов этого значения записываются в память с помощью инструкции sb (эффективно «обрезая» это значение в памяти, невозможно читать из памяти полное значение, только усеченную часть).


Преобразование в другом направлении также часто происходит в сборке MIPS, потому что, например, lb будет считывать только 8 бит из памяти, но будет расширять их до полного регистра (32 бита). Если вы не обращаете внимания на свои ценности, вы можете легко поймать себя в ловушку, например, так:

.data
test_value: .byte 234
.text
    li      $t0, 234
    lb      $t1, test_value
    tne     $t0, $t1     # throw exception if t0 is not equal to t1
    # terminate normally when values are equal
    li      $v0, 10
    syscall

Это может выглядеть при первом прочтении, поскольку есть значение 234 по сравнению с 234, и, таким образом, программа обычно завершает свою работу, но если вы попытаетесь запустить ее, вместо этого она завершится исключением из инструкции tne. Поскольку lb действительно расширяет значение знака и 234 помещается в 8 бит только тогда, когда вы интерпретируете эту битовую комбинацию как «8-битное целое число без знака», если вы интерпретируете ту же битовую комбинацию как «8-битное целое число со знаком», становится значением -22. И -22 не равно 234.

Если вы измените инструкцию lb на lbu, которая загружает «беззнаковый байт», код будет работать и нормально работать, поскольку tne будет сравнивать 234 против 234 значений, которые равны.

Таким образом, при программировании на ассемблере вы должны точно знать тип обрабатываемых данных и корректно расширять / усекать эти значения по мере необходимости.

(Кстати, ассемблер MARS предупредит вас о том, что «234» не соответствует «байту со знаком» и возможному усечению - но значения до 255 на самом деле соответствуют 8 битам, просто их нужно интерпретировать «без знака» ... значения выше) 255 будет по-настоящему обрезано, как будто некоторые биты полностью отсутствуют, например, .byte 1025 сохранит в памяти только значение 1)

...