I have these lines of code that are supposed to set carry flag to 1. I ran this code through emulator in emu8086 and it showed me that carry flag is not set. In my opinion, carry flag should be set beacuse number 0xC7 (in binary: 1100 0111) is moved to left, so carry flag should return 1. Hope that someone can help.
.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
So you want to do a 16-bit shift but have CF set from the top of the low half? I don't know why you want that, especially if you're going to jnc
instead of using adc cl, 0
to do CL += CF.
There are more efficient ways to popcnt the high nibble of a register, e.g. make a copy of the register and actually shift bits out instead of just withing a register. Or use the popcnt
instruction after isolating those bits in a register, if you can assume a modern CPU.
Anyway, there's no single instruction for that, but there are a couple options for setting CF according to a bit, depending on what CPU compatibility you need. The most straightforward is:
;; 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
There's also this way that's probably slow on old CPUs: x86 shifts/rotates mask the count with &31
(or &63
for 64-bit shifts) so shifts/rotates narrower than 32-bit can use a count as large as the operand-size and have it not count as 0.
rol
sets CF according to the last bit that "wrapped around" from high to low. A count of 8 for an 8-bit register leaves it unmodified, with the last bit rotating around being the low bit. Also, CPUs before 286 didn't mask the count anyway, they just took as many clock cycles as the shift count. (So this is pretty slow on old CPUs without a barrel shifter for constant-time rotates.)
Or if the Operation section of the manual reflects the actual 286 implementation, rotates do mod size
for the actual shifting work, but the count != 0
check to see if it sets FLAGS at all is based on count & 1Fh
not count mod 8
. And if it does, 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
Obviously it's easier to set ZF according to a specific bit, e.g.
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:
But branching sucks vs. adc
.
Note that shl
by 1 has basically no advantages except you can use it with a register destination. On some CPUs it's more efficient to use add ax,ax
to left-shift. It even sets CF the same way (according to what was previously the top bit).