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
)