Как решить проблему переноса 8-битного значения в регистр BX (16-битный)?
mov al, 10h
mov bx, al
за это я получаю:
operands do not match: 16 bit and 8 bit register
Как решить проблему переноса 8-битного значения в регистр BX (16-битный)?
mov al, 10h
mov bx, al
за это я получаю:
operands do not match: 16 bit and 8 bit register
Ответ зависит от того, хотите ли вы расширить значение до нуля или до знака, а также от того, можете ли вы использовать инструкции, доступные, начиная с 80386. Для повышения производительности следует использовать код 80386 или более поздней версии, если доступны movzx
и movsx
.
Обнулите верхнюю половину, затем перейдите к нижней половине.
xor bh, bh
mov bl, al
(Или, что эквивалентно и более эффективно для некоторых более поздних процессоров, xor bx, bx
для обнуления всех 16 бит перед заменой младших 8.)
Без 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 добавила версии некоторых из них, которые работают с любым регистром.
Используйте movzx
.
movzx bx, al
Для наилучшей производительности нуль расширяется до 32 бит.
movzx ebx, al
Используйте movsx
, что похоже на cbw
, но работает для любых dst, src< /em>, даже включая источник памяти.
movsx bx, al
Если возможно, расширьте знак до 32 бит для повышения производительности.
movsx ebx, al
Другие методы: также возможна установка верхней половины с помощью neg
/sbb
, а также арифметические сдвиги или логические сдвиги для расширения знака или нуля. (Особенно, если ваше значение начинается в таком регистре, как AH). См. MASM Ассемблер перемещает 8-битный регистр в 16-битный регистр (т.е. mov cx, ch)
cbw
/ mov bx, ax
на 8086.
- person Peter Cordes; 08.11.2019
xor bx,bx
во-первых, вероятно, лучше, чем xor bh,bh
. Он по-прежнему имеет ложную зависимость от старого значения, потому что он не записывает полные 32 бита, которые доступны в 16-битном режиме, но в семействе P6 он, возможно, избежит частичной остановки регистрации при чтении полного bx. (Не уверен, что это верно для 16-битных регистров). Написание BH также вводит BH-слияние на SnB-семейство. Я понимаю вашу мысль о том, что некоторым людям может быть проще понять, как писать верхнюю/нижнюю половины отдельно.
- person Peter Cordes; 08.11.2019
cbw
достаточно, так как это также хорошо для размера кода. (И расширение до 32-бит для 386 - это хорошо)
- person Peter Cordes; 08.11.2019
test
всегда очищает CF. Я думаю, вам нужно cmp al, 80h
+ cmc
или что-то еще, чтобы установить CF в соответствии с битом знака AL. Или какой-нибудь однобайтовый xchg ax,bx
материал вокруг CBW. (Я комментировал этот блок во время редактирования; это заставило меня задуматься о том, какой флаг SBB на самом деле читает)
- person Peter Cordes; 08.11.2019
mov bx, ax
/ cbw
/ xchg bx, ax
- это способ с наименьшим размером кода, позволяющий избежать разрушения AH, и производительность, аналогичная или лучшая для cmp/cmc/sbb на современных процессорах (особенно Intel до Broadwell, где SBB составляет 2 моп). Пришлось позволить этому подпрыгивать в моей голове некоторое время, чтобы прийти к нему.
- person Peter Cordes; 08.11.2019
movzx bx, al
,movsx bx, al
илиxor bh, bh; mov bl, al
. - person Jester   schedule 08.11.2019movzx ebx, al
для записи полного регистра вместо 16-битного частичного регистра. - person Peter Cordes   schedule 08.11.2019