Сборка - инструкция SHL не включает флаг переноса - PullRequest
0 голосов
/ 09 июня 2019

У меня есть эти строки кода, которые должны установить флаг переноса в 1. Я запустил этот код через эмулятор в emu8086, и он показал мне, что флаг переноса не установлен. По моему мнению, флаг переноса должен быть установлен, поскольку число 0xC7 (в двоичном виде: 1100 0111) перемещено влево, поэтому флаг переноса должен возвращаться 1. Надеюсь, что кто-то может помочь.

.model small

.data

.code

main proc
mov ax, 0xC7          
xor cl , cl 
shl ax,1 
jnc a1 
inc cl
a1:
shl ax,1 
jnc a2 
inc cl
a2:
shl ax,1 
jnc a3 
inc cl
a3:
shl ax,1 
jnc a4 
inc cl
a4:

endp

end main

1 Ответ

0 голосов
/ 10 июня 2019

То есть, вы хотите сделать 16-битный сдвиг, но установить CF с верха нижней половины?Я не знаю, почему вы этого хотите, особенно если вы собираетесь jnc вместо использования adc cl, 0 для выполнения CL + = CF.

Существуют более эффективные способы подсунуть высокий клеврегистр, например, сделать копию регистра и фактически сдвинуть биты вместо того, чтобы просто использовать регистр.Или используйте инструкцию popcnt после выделения этих битов в регистре, если вы можете предположить, что современный процессор.


В любом случае, для этого нет единой инструкции, но есть пара вариантов для установки CFсогласно немного, в зависимости от того, какая совместимость процессора вам нужна.Наиболее простым является:

;; 386 for BT/BTS
   shl   ax, 1
   bt    ax, 8        ; set CF from the bit that was previously the top of AL

   adc   cl, 0        ; CL += CF

Существует также способ, который, вероятно, медленен на старых процессорах: x86 сдвигает / вращает, маскируя счет с &31 (или &63 для 64-разрядных сдвигов), поэтому сдвиги /вращается уже 32-битного может использовать счет, равный размеру операнда, и не считать его равным 0.

rol устанавливает CF в соответствии с последним битом, который "обернут"вокруг "от высокого до низкого.Счет 8 для 8-битного регистра оставляет его неизменным, а последний бит, вращающийся вокруг, является младшим битом.Кроме того, процессоры до 286 не маскировали счет в любом случае, они просто взяли столько тактов, сколько счетчик смен.(Так что это довольно медленно на старых процессорах без бочкообразного сдвига для вращений с постоянным временем.)

Или, если в разделе Руководство по эксплуатации отражена фактическая реализация 286, вращается до mod size для фактической работы смены, но проверка count != 0, чтобы увидеть, устанавливает ли он флаги вообще, основана на count & 1Fh, а не count mod 8.И если это так, CF = LSB(dest)

;; 186 for immediate-count shifts/rotates
   shl   ax, 1
   rol   ah, 8        ; set CF from the bit that was previously the top of AL

   adc   cl, 0        ; CL += CF

Очевидно, что проще установить ZF в соответствии с конкретным битом, например,

   add   ax, ax     ; AX <<= 1
   test  ah, 1      ; ZF = low bit of AH

   ;test  ax, 1<<8   ; ZF = low bit of AH   same code size, actually
   jz   no_increment
   inc   cl
no_increment:

Но ветвление отстой против adc.

Обратите внимание, что shl 1 практически не имеет преимуществ, за исключением того, что вы можете использовать его с адресом регистрации.На некоторых процессорах более эффективно использовать add ax,ax для сдвига влево.Он даже устанавливает CF таким же образом (в соответствии с тем, что ранее было верхним битом).

...