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
CMPinstruction 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
JEinstruction you are already familiar with, except that it branches based on the value of the carry flag (CF), instead of the zero flag (ZF) likeJEdoes.To conditionally branch on the status of the carry flag (CF), you would use
JCorJNC.JCwill branch if the carry flag is set (CF == 1), whereasJNCwill 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
NUMin 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
SBBinstruction. 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 becauseSBBactually performs the operationDEST = (DEST - (SRC + CF)). WhenDESTandSRCare 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
NEGinstruction:In certain cases, you can even use the
ADCinstruction in an analogous manner. This performs the operationDEST = DEST + SRC + CF. WhenDESTandSRCare 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
CFin memory, you could use the following form ofADC:On more modern architectures, you could use either the
SETCorCMOVCinstructions (orSETNC/CMOVNCfor 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.