汇编-SHL指令未打开进位标志

时间:2019-06-09 20:59:44

标签: assembly x86 low-level carryflag

我有这些代码行应该将进位标志设置为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 :(得分:0)

那么您想进行16位移位,但是CF从下半部分的顶部开始设置?我不知道您为什么要这么做,尤其是如果您要去jnc而不是使用adc cl, 0来进行CL + = CF。

有很多更有效的方法可以使寄存器的高位字节有效,例如复制寄存器并实际移出位,而不是仅移入寄存器。如果可以使用现代CPU,或者在隔离寄存器中的那些位后使用popcnt指令。


无论如何,没有一个单独的指令,但是有几个选项可以根据需要设置CF,具体取决于所需的CPU兼容性。最直接的是:

;; 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

还有这种方法在旧CPU上可能很慢:x86移位/旋转用&31(对于64位移位,则是&63来掩盖计数),因此移位/旋转范围比32位窄< em>可以使用与操作数大小一样大的计数,而不是将其计数为0。

rol根据从高到低“缠绕”的最后一位来设置CF。 8位寄存器的8计数保持不变,最后一位为低位。此外,286之前的CPU仍然没有掩盖计数,它们只占用与移位计数一样多的时钟周期。 (因此,在没有桶形移位器进行恒定时间旋转的旧式CPU上,这相当慢。)

或者如果Operation section of the manual反映了实际的286实现方式,则将mod size旋转进行实际的换档工作,但是count != 0检查是否是否完全基于{ {1}}不是count & 1Fh。如果有,count mod 8

CF = LSB(dest)

显然,根据特定位设置ZF更加容易,例如

;; 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

但是分支与 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乘以1基本上没有任何好处,除非您可以将其与寄存器目标一起使用。在某些CPU上,使用shl左移更为有效。它甚至以相同的方式设置CF(根据之前的最高位)。