MASM Assembly перемещает 8-битный регистр в 16-битный регистр (т.е. mov cx, ch)
Я решил выучить ассемблерный язык программирования. Я использую это. В нижней части упражнения это найти ошибку в некоторых инструкциях, и одна из них
mov cx, ch
В этой теме я нашел похожий вопрос по SO, объясняющий, как этого добиться, но теперь я хотел бы знать, почему эта операция запрещена?
Предположим, у меня есть 10d = 00001010b в канале и я хочу поместить его в CL и одновременно стереть канал. mov cx, ch
кажется, делает это, потому что он показывает 10d как 16 бит 00000000 00001010 и устанавливает его соответственно в CH и CL (весь CX)
Что с ним не так и почему данное руководство просит найти ошибку в этом выражении?
3 ответа
mov
Инструкция используется для перемещения между операндами одинакового размера. То, что вы хотите, это расширить 8-битный ch
в 16-битный cx
, Для этого есть две инструкции:
movzx cx,ch ; zero-extends ch into cx. the upper byte of cx will be filled with zeroes
movsx cx,ch ; sign-extends ch into cx. the upper byte of cx will be filled with the most significant bit of ch
Другой способ сделать то же самое в данном конкретном случае:
shr cx,8 ; zero-extend
sar cx,8 ; sign-extend
Вы хотите переместить содержимое CH
к CX
на 8086.
На более новых процессорах, таких как 80286, вы можете просто изменить значение CX
справа на 8 позиций, с тиражированием знака или без:
; zero extend ch into cx
shr cx,8
; sign extend ch into cx
sar cx,8
Эти инструкции недоступны для 8088 или 8086. Вы можете использовать CL
чтобы указать количество смен:
; zero extend ch into cx
mov cl,8
shr cx,cl
; sign extend ch into cx
mov cl,8
sar cx,cl
Однако этот метод очень медленный, потому что сдвиг на переменное количество позиций занимает несколько циклов на позицию.
Вот более быстрый способ:
; zero extend ch into cx
mov cl,ch
xor ch,ch
; sign extend ch into cx
mov cl,ch
neg ch ; set the carry flag if ch is negative
sbb ch,ch ; set all bits if ch was negative, clear them otherwise
Если вы можете уничтожить AX, вы можете сэкономить размер кода, используя cbw
который предназначен для этого. В исходном 8086 и особенно 8088 small = fast, потому что выборка кода была основным узким местом. Однако это не так на современных x86.
; sign extend ch into ax
mov al, ch
cbw ; sign-extend AL into AX
; optionally move back to cx
xchg cx, ax ; smaller than mov cx, ax
Чтобы избежать разрушения AX, вы можете сделать mov cl,ch
; xchg ax,cx
; cbw
и остановись на этом, или сделай последний xchg ax,cx
просто подписать-расширить CH в CX и восстановить все остальное. xchg
с AX - это 1-байтовая инструкция, как и cbw
а также cwd
(расширить AX до DX:AX, например, до 16-битного idiv
)
cbw
в точности как 386 movsx ax, al
.
Проблема в том, что вы пытаетесь переместить содержимое 8-битного регистра ch
в 16-битный регистр cx
, Вы не можете сделать это, потому что регистры разных размеров.
Поэтому я предполагаю, что вы получите сообщение об ошибке типа "недопустимая комбинация кода операции и операндов".
PS: обмен 8 и 16 выше; утверждение остается прежним. Проверьте, например, этот обзор. Как видите, комбинация разных размеров регистров не определена. Это означает, что не существует никакого OPcode, который представляет mov cx, ch
,
Просто сделай это с простыми инструкциями
mov cl,ch ; copy high bits to low
xor ch,ch ; clear high-bits
это распространено в 16-битном программировании и занимает всего 2 такта.
Для использования movezx / movsx требуется 3 такта. использование
movsx cx,ch
для перемещения байта в слово с расширением s ign и
movzx cx,ch
Переместить байт в слово с z эро-расширением