According to Intel's Software Developer's Manual "JB" stands for "Jump if Below"
5.1.7 Control Transfer Instructions
The control transfer instructions provide jump, conditional jump, loop, and call and return operations to control program flow.
- JE/JZ Jump if equal/Jump if zero
- JNE/JNZ Jump if not equal/Jump if not zero
- JA/JNBE Jump if above/Jump if not below or equal
- JAE/JNB Jump if above or equal/Jump if not below
- JB/JNAE Jump if below/Jump if not above or equal
- JBE/JNA Jump if below or equal/Jump if not above
- JG/JNLE Jump if greater/Jump if not less or equal
- JGE/JNL Jump if greater or equal/Jump if not less
- JL/JNGE Jump if less/Jump if not greater or equal
- JLE/JNG Jump if less or equal/Jump if not greater
- JC Jump if carry
- JNC Jump if not carry
- JO Jump if overflow
- JNO Jump if not overflow
- JS Jump if sign (negative)
- JNS Jump if not sign (non-negative)
- JPO/JNP Jump if parity odd/Jump if not parity
- JPE/JP Jump if parity even/Jump if parity
There are only 8 types of conditions (and their inverses, so 16 total) that x86 conditional branch recognizes. Which mnemonic (synonym) you use depends on the situation, usually you would use whatever makes more sense. If you disassemble code then the disassembler may not be smart enough to select the most meaningful choice. Note in the list above Intel lists 18 conditional jumps instead of 16, that's because
- JB/JNAE/JC all assemble to the same instruction
- JAE/JNB/JNC all assemble to the same instruction
Here's a convenient table with the synonyms grouped together.
JB is usually used after "CMP", something like this
cmp dh,dl
jb loc_123456 ; jump if DH is below DL
"JB" branches if the Carry flag is set. As noted earlier you could also do the same conditional branch with JNAE "Jump if Not Above or Equal"
cmp dh,dl
jnae loc_123456 ; jump if DH is not above or equal to DL
or with "JC"
cmp dh,dl
jc loc_123456 ; jump if there was a carry (borrow) when subtracting DL from DH
In your case it would probably be a better choice to use "JC", jump if carry set
add dh, dl ; These are both unsigned integers.
jc loc_123456 ; Jump if carry set
It is convenient to think of the conditional branch as testing the result of the previous instruction - however the way it is defined in the x86 architecture the EFLAGS register is a "middle man" that holds the resulting condition codes. Certain instructions (usually arithmetic, logic, comparison) update the EFLAGS register to indicate the result of the operation, and the conditional branch instructions in turn use the EFLAGS register to determine whether to take the branch or not.
There are some arcane rules regarding which EFLAGS bits are computed by an instruction, sometimes always set to 1 or 0 regardless of the operands, for other instructions certain EFLAGS bits are undefined, and some instructions preserve certain EFLAGS bits (unchanged by the instruction). For example, the INC and DEC instructions preserve the contents of the Carry Flag in EFLAGS. Rotate instructions update Carry and Overflow flags and preserve the others, the Overflow flag is undefined after a rotate if the count is greater than one... etc.
Here's a contrived example to make the point. In this example the conditional branch is testing the result of two different instructions operating on two different 8-bit registers.
rol dl,1
inc dh
jnbe loc_123456
The ROL rotate instruction rotates DL left by one bit, sets the EFLAGS carry flag to the last bit rotated. The INC instruction increments DH by 1, preserves the EFLAGS carry flag, sets the other arithmetic flags in EFLAGs. The JNBE is a "Jump if Not Below or Equal" which branches if EFLAGS Carry Flag is zero and the EFLAGS Zero Flag is clear. The Zero Flag was cleared if after incrementing DH the DH register is not zero (which is true unless DH was 0xFF and after incrementing it wrapped to 0x00). The Carry Flag was set to match the last bit rotated left, in other words the least significant bit of DL after the rotate left (what was previously the most significant bit). JNBE makes little sense if you think of it as "Jump if Not Below or Equal", but it might make sense if you think of it as simply a test of whether the Carry flag and the Zero flag are both zero.
jc
, testing CF, and yes x86's carry flag does work as a "borrow" output from sub / cmp (unlike ARM for example where it's reversed.) – Pete