您不能使用CMP
直接指令,因为标志对于 x86 指令来说不是有效的操作数。它们仅由某些指令隐式使用。
最简单的解决方案就是使用条件分支 http://x86.renejeschke.de/html/file_module_x86_id_146.html。这类似于JE
您已经熟悉的指令,除了它基于进位标志(CF)的值而不是零标志(ZF)的值进行分支JE
does.
要根据进位标志 (CF) 的状态有条件地分支,您可以使用JC
or JNC
. JC
如果设置了进位标志(CF == 1),则将分支,而JNC
如果进位标志是则分支not设置(CF == 0)。这些操作码的助记符很简单“Jump if C阿里”和“Jump if Not Carry".
jc CarryFlagIsSet ; jump if CF == 1
; else fall through: code for CF == 0 goes here
或者用另一种方式来做:
jnc CarryFlagIsNotSet ; jump if CF == 0
; else fall through: code for CF == 1 goes here
因此,根据您的示例,类似:
shr num, 1 ; put least significant bit in CF
jc num_was_odd ; (or jnc LSBNotSet aka num_was_even)
But 正如彼得·科德斯在评论中指出的那样 https://stackoverflow.com/questions/41335653/how-to-check-cf-flag-is-1-in-emu8086/41345823#comment69885438_41335653,您的代码几乎肯定是错误的,因为无论是否采用分支,都会执行相同的代码。换句话说,分支目的地相当于失败代码。您可能想要更多类似的东西:
TOPOFLOOP:
LEA DX, MSG
MOV AH, 09H
INT 21H
MOV AH, 01H
INT 21H
MOV NUM, AL
SHR NUM, 1
JC TOPOFLOOP ; keep looping as long as CF == 1
; otherwise, if CF == 0, fall through to FINISH
; (use JNC to reverse the logic)
FINISH:
MOV AH, 4CH
INT 21H
RET
(除了它是much对注册值进行操作比对内存中存储的值进行操作更快,因此如果可能的话,您应该将NUM
在寄存器中。此外,汇编语言操作码和寄存器不区分大小写,因此您可以轻松地用小写字母编写代码。我认为这更容易输入和阅读,但这纯粹是风格上的,因此取决于你。)
当您想要编写无分支代码时(如果您能找到一种足够聪明的方法来编写代码,这几乎总是可以提高性能),您可以使用SBB操作说明 http://x86.renejeschke.de/html/file_module_x86_id_286.html。如果两个操作数是同一寄存器,则如果设置了进位标志 (CF == 1),则将该寄存器设置为 -1;如果未设置进位标志 (CF == 0),则将该寄存器设置为 0。这有效是因为SBB
实际执行操作DEST = (DEST - (SRC + CF))
. When DEST
and SRC
是相同的值,这相当于DEST = -CF
.
如果精确地获得寄存器的值镜像 CF 会更方便,则可以将其与NEG操作说明 http://x86.renejeschke.de/html/file_module_x86_id_216.html:
; Perform operation that will set CF.
...
; Set AX to the same value as CF.
sbb ax, ax ; CF == 1 then AX = -1; otherwise, AX = 0
neg ax ; AX == -1 then AX = 1; otherwise, AX = 0
在某些情况下,您甚至可以使用ADC操作说明 http://x86.renejeschke.de/html/file_module_x86_id_4.html以类似的方式。这将执行操作DEST = DEST + SRC + CF
. When DEST
and SRC
都为零,这相当于DEST = CF
。棘手的部分是,目标寄存器必须在进位标志设置之前预先清零,或者以不影响进位标志的方式清零:
; Pre-zero AX in preparation for later use of ADC.
xor ax, ax
; Perform operation that will set CF.
; (NOTE: Cannot modify AX register here, nor AL nor AH!)
...
; Set AX to the same value as CF.
adc ax, ax
; Perform operation that will set CF.
...
; Zero AX in such a way that flags are not clobbered.
mov ax, 0
; Set AX to the same value as CF.
adc ax, ax
请注意,如果您想存储CF
在内存中,您可以使用以下形式ADC
:
adc DWORD PTR [value], 0
在更现代的架构上,您可以使用SETC
or CMOVC
说明(或SETNC
/CMOVNC
对于逆逻辑——助记符与JC
/JNC
)。这些通常是编写无分支代码的更快方法;然而,这两者在 8086 上都不可用。条件集 (SETcc) 指示 http://x86.renejeschke.de/html/file_module_x86_id_288.html随 386 一起推出,同时条件移动 (CMOVcc) http://x86.renejeschke.de/html/file_module_x86_id_34.html是随 Pentium Pro 一起推出的。