MOV 8-битный регистр в 16-битном (от al до bx)

Как решить проблему переноса 8-битного значения в регистр BX (16-битный)?

mov al, 10h
mov bx, al

за это я получаю:

operands do not match: 16 bit and 8 bit register 

person Slack Bot    schedule 08.11.2019    source источник
comment
Вам нужно преобразовать размер или полагаться на частичные регистры. Например. movzx bx, al, movsx bx, al или xor bh, bh; mov bl, al.   -  person Jester    schedule 08.11.2019
comment
Или лучше movzx ebx, al для записи полного регистра вместо 16-битного частичного регистра.   -  person Peter Cordes    schedule 08.11.2019
comment
@PeterCordes мы не знаем, 16-битный это код или 32-битный :)   -  person Jester    schedule 08.11.2019
comment
@Jester: он не помечен x86-16, поэтому я предположил, что это современный x86. Даже в 16-битном режиме на современном ЦП дополнительный байт префикса размера операнда позволит избежать ложной зависимости от старого значения EBX. 32-битные регистры доступны в 16-битном режиме. Таков был мой мыслительный процесс, когда я рекомендовал писать ebx, даже если это был 16-битный код.   -  person Peter Cordes    schedule 08.11.2019
comment
Я добавил тег x86 :)   -  person Jester    schedule 08.11.2019
comment
@Jester: ах. это, вероятно, emu8086 или какая-то другая устаревшая вещь, учитывая сообщения OP о том, что они не работают. К счастью, Фуз ответил за оба случая.   -  person Peter Cordes    schedule 08.11.2019
comment
Сообщение об ошибке является ошибкой, сгенерированной emu8086, поэтому нет никаких сомнений в отношении среды. Я обновил теги.   -  person Michael Petch    schedule 08.11.2019
comment
Связанный, в основном дубликат: Сборка MASM перемещает 8-битный регистр в 16-битный регистр (т.е. mov cx, ch)   -  person Peter Cordes    schedule 18.11.2019


Ответы (1)


Ответ зависит от того, хотите ли вы расширить значение до нуля или до знака, а также от того, можете ли вы использовать инструкции, доступные, начиная с 80386. Для повышения производительности следует использовать код 80386 или более поздней версии, если доступны movzx и movsx.

нулевое расширение на 8086 или 80286

Обнулите верхнюю половину, затем перейдите к нижней половине.

xor bh, bh
mov bl, al

(Или, что эквивалентно и более эффективно для некоторых более поздних процессоров, xor bx, bx для обнуления всех 16 бит перед заменой младших 8.)

знак расширяется на 8086 или 80286

Без movsx вы, вероятно, захотите использовать cbw, который работает только с AL -> AX. Самый простой способ перезаписать AH перед копированием в BX, так как ваше значение уже было в AL.

 cbw               ; AH = 0 or 0xFF according to top bit of AL
 mov  bx, ax

Если вы хотите сохранить AH, вы можете сначала скопировать старый AX, а затем поменять местами после cbw:

 mov  bx, ax      ; save the old AH (and AL)
 cbw              ; sign-extend AL into AX
 xchg bx, ax      ; BX = sign-extended result, restore original AX

Сохранение инструкций на 8086 может включать в себя планирование того, что вы храните в каком регистре, чтобы он уже был в нужном месте для инструкции, такой как cbw или mul, которая использует неявный регистр. К 386 Intel добавила версии некоторых из них, которые работают с любым регистром.


нулевое расширение на 80386 или новее

Используйте movzx.

movzx bx, al

Для наилучшей производительности нуль расширяется до 32 бит.

movzx ebx, al

расширение знака на 80386 или новее

Используйте movsx, что похоже на cbw, но работает для любых dst, src< /em>, даже включая источник памяти.

movsx bx, al

Если возможно, расширьте знак до 32 бит для повышения производительности.

movsx ebx, al

Другие методы: также возможна установка верхней половины с помощью neg/sbb, а также арифметические сдвиги или логические сдвиги для расширения знака или нуля. (Особенно, если ваше значение начинается в таком регистре, как AH). См. MASM Ассемблер перемещает 8-битный регистр в 16-битный регистр (т.е. mov cx, ch)

person fuz    schedule 08.11.2019
comment
Если вы можете уничтожить AH, вы можете cbw / mov bx, ax на 8086. - person Peter Cordes; 08.11.2019
comment
Ваше редактирование делает код менее эффективным, если он работает на некоторых современных процессорах. xor bx,bx во-первых, вероятно, лучше, чем xor bh,bh. Он по-прежнему имеет ложную зависимость от старого значения, потому что он не записывает полные 32 бита, которые доступны в 16-битном режиме, но в семействе P6 он, возможно, избежит частичной остановки регистрации при чтении полного bx. (Не уверен, что это верно для 16-битных регистров). Написание BH также вводит BH-слияние на SnB-семейство. Я понимаю вашу мысль о том, что некоторым людям может быть проще понять, как писать верхнюю/нижнюю половины отдельно. - person Peter Cordes; 08.11.2019
comment
@PeterCordes Я знаю. Учитывая, что OP явно не программирует в контексте, чувствительном к производительности, образовательная часть здесь важнее. - person fuz; 08.11.2019
comment
Меня не волнует OP, я забочусь о том, чтобы это был хороший канонический ответ для будущих читателей, которые будут использовать его непосредственно в любом проекте, если им нужно искать и находить этот ответ. - person Peter Cordes; 08.11.2019
comment
Если подумать, потери производительности в 16-битном коде меня не особо беспокоят. Если люди пишут 16-битный код, они сами виноваты в том, что он работает медленно. Включение моего предложения cbw достаточно, так как это также хорошо для размера кода. (И расширение до 32-бит для 386 - это хорошо) - person Peter Cordes; 08.11.2019
comment
Минуточку, тест /sbb работает? test всегда очищает CF. Я думаю, вам нужно cmp al, 80h + cmc или что-то еще, чтобы установить CF в соответствии с битом знака AL. Или какой-нибудь однобайтовый xchg ax,bx материал вокруг CBW. (Я комментировал этот блок во время редактирования; это заставило меня задуматься о том, какой флаг SBB на самом деле читает) - person Peter Cordes; 08.11.2019
comment
mov bx, ax / cbw / xchg bx, ax - это способ с наименьшим размером кода, позволяющий избежать разрушения AH, и производительность, аналогичная или лучшая для cmp/cmc/sbb на современных процессорах (особенно Intel до Broadwell, где SBB составляет 2 моп). Пришлось позволить этому подпрыгивать в моей голове некоторое время, чтобы прийти к нему. - person Peter Cordes; 08.11.2019
comment
Уже собирался сохранить свое редактирование, когда выскочило ваше. Рад, что вы не внесли серьезных изменений, которые противоречили друг другу. - person Peter Cordes; 08.11.2019