CMPSB subtracts the byte at ES:DI from the byte at DS:SI, sets the flags from the result, throws the result away, and moves SI and DI to the next element (+1 with DF = 0, -1 with DF = 1; CMPSW compares words and steps by 2). Neither string changes.
Which way it subtracts
The flags are those of CMP DS:[SI], ES:[DI]: source minus destination. That is the opposite of what the register names suggest if you think of SUB dst, src. So after CMPSB, JB means the byte of the SI string was below the byte of the DI string. SCASB also subtracts the ES:DI element, from AL: in both, the ES:DI side is the right-hand operand of the comparison.
| After CMPS | Jumps when |
|---|---|
| JE / JZ | [SI] = [DI] |
| JB / JA | [SI] below / above [DI], unsigned (text) |
| JL / JG | [SI] less / greater than [DI], signed |
Comparing strings
With REPE the comparison repeats while CX is not 0 and the elements are equal. When it stops, ZF tells you why: ZF = 1 means all CX elements matched, ZF = 0 means a difference. Test ZF, not CX: a difference in the very last element also leaves CX = 0. SI and DI then point one past the differing elements, so the 0-based index of the difference is SI - start - 1 (bytes, going forward). If CX was 0 to begin with, nothing is compared and the flags are left as they were.
CLDMOV SI, OFFSET STR1MOV DI, OFFSET STR2MOV CX, 5REPE CMPSB ; stop at the first differenceMOV DL, '=' ; MOV leaves the flags aloneJE SHOW1 ; all five equalMOV DL, '<'JB SHOW1 ; "e" is below "y"MOV DL, '>'SHOW1:MOV AH, 02hINT 21hSTR1 DB 'apple'STR2 DB 'apply'
REPNE CMPSB is the opposite: it stops at the first position where the two strings are equal. A source override (CMPS BYTE PTR CS:[SI], ES:[DI]) is allowed; ES:DI is fixed. In an .EXE, set ES before comparing.