По умолчанию, если мы хотим копировать данные из одного регистра в другой, то оба регистра должны иметь одну и туже разрядность, например, оба должны быть или 64-битными или 32-битными. Кроме того, при копировании копируется все содержимое одного регистра в другой. Но иногда может возникнуть необходимость скопировать только часть регистра. Для этого ассемблер ARM предоставляет ряд инструкций:
SXTB Xd, Wn SXTH Xd, Wn SXTW Xd, Wn UXTB Xd, Wn UXTH Xd, Wn UXTW Xd, Wn SXTB Wd, Wn SXTH Wd, Wn UXTB Wd, Wn UXTH Wd, Wn
SXTB: копирование со знаком 8 бит второго операнда в первый операнд. Остальные биты первого операнда заполняются знаковым битом второго операнда.
SXTH: копирование со знаком 16 бит второго операнда в первый операнд. Остальные биты первого операнда заполняются знаковым битом второго операнда.
SXTW: копирование со знаком 32 бит второго операнда в первый операнд. Остальные биты первого операнда заполняются знаковым битом второго операнда.
UXTB: беззнаковое копирование 8 бит второго операнда в первый операнд. Остальные биты первого операнда заполняются нулем.
UXTH: беззнаковое копирование 16 бит второго операнда в первый операнд. Остальные биты первого операнда заполняются нулем.
UXTW: беззнаковое копирование 32 бит второго операнда в первый операнд. Остальные биты первого операнда заполняются нулем.
В качестве первого операнда может выступать 64-разрядные регистры X0-X30, тогда расширение копируемого числа идет до 64 бит, либо 32-разрядные регистры W0-W30, тогда расширение идет до 32 бит.
Например:
mov w1, #259 // 0b00000001_00000011 uxtb x0, w1 // X0 = 0b00000011 = 3
Здесь копируем первый байт из W1 в X0. Поскольку копирование беззнаковое, то старшие 7 байт в X0 будут заполняться нулями.
Инструкции SXTB/SXTH/SXTW выполняют копирование со знаком, причем знак берется из старшего бита копируемой части регистра.
Например, перепишем предыдущий пример, только используем копирование младшего байта с расширением со знаком с помощью инструкции SXTB
mov w1, #259 // 0b00000001_00000011 sxtb x0, w1 // X0 = 0b00000011 = 3
Здесь также компируется младший байт - 00000011
, только теперь идет расширение со знаком. Старший бит в копируемом байте равен 0 - знак положительного числа, поэтому
старшие 7 байт в X0 также будут заполняться нулями.
Рассмотрим другой примере
mov w1, #-253 // 0b11111111_00000011 sxtb x0, w1 // X0 = 0b00000011 = 3
Здесь в W1 помещается отрицательное число -253, что в бинарной форме равно 0b11111111_11111111_11111111_00000011
. Инструкция sxtb
копирует младший байт,
в котором старший бит равен 0. Следовательно в X0 опять же будет располагаться число 3 (положительное). Несмотря на то, что в регистре W1 находится отрицательное число.
И последний пример:
mov w1, #129 // 0b00000000_10000001 sxtb x0, w1 // X0 = 0b11111111_10000001
Теперь в W1 число положительное - 129 или 0b10000001
в бинарной форме. Также извлекаем младший байт и расширяем его знаком. Но теперь в страший бит извлекаемого байта равен 1 -
показатель отрицательного числа. Поэтому в X0 будет располагаться отрицательное число 0b11111111_10000001
или -127 десятичной форме.