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 эро-расширением

Другие вопросы по тегам