I am trying to find if the CARRY flag is 1 or not, but I don't know how to check it. I wrote the below code, but I need some help for question marks I put in.
LEA DX, MSG
MOV AH, 09H
INT 21H
MOV AH, 01H
INT 21H
MOV NUM, AL
SHR NUM, 1
CMP ??, 1
JE FINISH
FINISH: MOV AH, 4CH
INT 21H
NUM DB 0
RET
You cannot use the
CMP
instruction directly, since the flags are not valid operands for x86 instructions. They are only used implicitly by certain instructions.The simplest solution is just to use a conditional branch. This works analogously to the
JE
instruction you are already familiar with, except that it branches based on the value of the carry flag (CF), instead of the zero flag (ZF) likeJE
does.To conditionally branch on the status of the carry flag (CF), you would use
JC
orJNC
.JC
will branch if the carry flag is set (CF == 1), whereasJNC
will branch if the carry flag is not set (CF == 0). The mnemonics for these opcodes are simply "Jump if Carry" and "Jump if Not Carry".Or do it the other way:
So, in keeping with your example, something like:
But as Peter Cordes points out in a comment, the code you have is almost certainly wrong, since the identical code will be executed whether or not the branch is taken. In other words, the branch destination is equivalent to the fall-through code. You probably want to have something more like:
(Except that it is much faster to operate on an enregistered value than one stored in memory, so if possible, you should place
NUM
in a register. Also, assembly language opcodes and registers are case-insensitive, so you can just as easily write the code in lowercase. I think this is both easier to type and easier to read, but it's purely stylistic and therefore up to you.)When you want to write branchless code (which almost always improves performance, if you can figure out a clever enough way to write the code), you can use the
SBB
instruction. If both operands are the same register, this will set that register to -1 if the carry flag is set (CF == 1), or set that register to 0 if the carry flag is not set (CF == 0). This works becauseSBB
actually performs the operationDEST = (DEST - (SRC + CF))
. WhenDEST
andSRC
are the same value, this is equivalent toDEST = -CF
.In cases where it would be more convenient to have the register's value mirror CF exactly, this can be combined with the
NEG
instruction:In certain cases, you can even use the
ADC
instruction in an analogous manner. This performs the operationDEST = DEST + SRC + CF
. WhenDEST
andSRC
are both zero, this is equivalent toDEST = CF
. The tricky part about this is that the destination register has to be either pre-zeroed before the carry flag gets set, or zeroed in such a way that the carry flag is not affected:Note that if you wanted to store the value of
CF
in memory, you could use the following form ofADC
:On more modern architectures, you could use either the
SETC
orCMOVC
instructions (orSETNC
/CMOVNC
for the converse logic—the mnemonics are the same asJC
/JNC
). These are generally even faster ways to write branchless code; however, neither are available on the 8086. Conditional set (SETcc
) instructions were introduced with the 386, while conditional moves (CMOVcc
) were introduced with the Pentium Pro.