Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does "jb" signify if preceded by an "add" command?

Lets say I have the following instructions in x86

add dh, dl            ; These are both unsigned integers.
jb loc_123456

What does jb signify in this context? Generally it means "jump if below", but I'm not sure what that means in this context.

like image 236
Kevin Burke Avatar asked Dec 08 '22 08:12

Kevin Burke


1 Answers

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.

like image 177
amdn Avatar answered Dec 30 '22 09:12

amdn