42

I'm very new to assembly and now I'm trying to understand how cmp works. Here is what's written in wiki:

cmp arg2, arg1

Performs a comparison operation between arg1 and arg2. The comparison is performed by a (signed) subtraction of arg2 from arg1, the results of which can be called Temp. Temp is then discarded.

What does it mean "Temp is then discarded"? Where is it stored? How can I access this result of the comparison? Can someone explain it?

4
  • @Carcigenicate *ax? Cos AFAIK it's often used with je. But je needs to know if condition was true or false. Commented Aug 26, 2017 at 18:24
  • 1
    Note that you're referring to wikibooks, which is a particular collection of wikis. A wiki is just a type of website that users can edit. And as such, wikibooks definitely isn't the prime ressource for x86 assembly definitions (this one is a good example why it's sometimes better to rely on expert documentation than user-generated documentation). Use google to find another source, and interpret that! Commented Aug 26, 2017 at 18:25
  • 2
    je doesn't need to know if condition was true or false, je is alias of jz, and jz is "jump if zero flag is set". So whatever last instruction did modify the ZF, that one will foretold whether next je will take a jump (ZF=1) or not (ZF=0). One of the funny consequences of new asm programmers not getting it, is writing code like sub ax,1 cmp ax,0 jne myLoop ... that cmp is not needed there, as previous sub will already set ZF in a sufficient way for that jne work (but more logical would be to use jnz myLoop alias, i.e. reads as "jump not zero loop" - almost English. Commented Aug 26, 2017 at 20:11
  • 3
    "The comparison is performed by a (signed) subtraction" -- Subtraction with 2's complement numbers isn't either signed or unsigned, both are the exact same operation. jz/je and jnz/jne don't care about whether a comparison was signed or unsigned, either. However, other x86 comparison conditional branches do need to be specified as signed or unsigned. Signed ones are called "jump if (not) less/less-or-equal/greater/greater-or-equal", giving the instructions jl, jg, etc. Unsigned comparison conditionals are called "jump if (not) below/above/etc", jb, ja, etc. Commented May 3, 2020 at 19:26

6 Answers 6

64

cmp arg2, arg1 performs the same operation as sub arg2, arg1 except that none of the operands are modified. The difference is not stored anywhere.

However, the flags register is updated and can be used in a conditional jump, like jump-if-equal (JE), most often as the next instruction after the cmp.

The advantage over other instructions is that you can compare two values without destroying any of them. If you did sub arg2, arg1 and they happen to be equal, one of them would be zero afterwards. With cmp they are both still there.

Sign up to request clarification or add additional context in comments.

2 Comments

Are the args the same in Intel and ATT?
@Thoth: As always, AT&T reverses the order of the arg list vs. Intel syntax. So AT&T cmp %eax, %ecx is Intel cmp ecx, eax. You have to think in the other direction for mnemonics like jl and jb to make sense in AT&T.
49

the results of CMP is changing the values of ZF and CF, this is some examples to understand very much CMP instruction.

Example 1: if AX < BX

MOV AX,5
MOV BX,8
CMP AX,BX 

Result : ZF and CF set to ==> "ZF = 0" and "CF = 1"



Example 2 : if AX > BX

MOV AX,8
MOV BX,5
CMP AX,BX

Result : ZF and CF set to ==> "ZF = 0" and "CF = 0"



Example 3 : if AX = BX

MOV AX,5
MOV BX,AX
CMP AX,BX 

Result : ZF and CF set to ==> "ZF = 1" and "CF = 0"



i hope you understand the results of CMP is changing the value of ZF and CF
ZF = Zero Flag
CF = Carry Flag

Comments

18

We use cmp arg2, arg1 when we care about whether arg1 and arg 2 are equal. The processor determines this by subtracting arg2 from arg1, then looking at the result. If the result is zero (that is, arg1 = arg2), then the processor sets the zero flag (by "sets the flag", we mean it sets it to 1). Conversely, if the result isn't zero (that is, arg1 != arg2), then the processor clears the zero flag (i.e, sets it to 0). The result itself is discarded, because we don't care what it is, only whether it's zero or not, which we now know based on whether the zero flag is set. We can then use instructions like JE, JNE, JZ and JNZ that examine the zero flag and jump (or not) based on its value. In the case of JE (jump if equal), the jump will happen if the zero flag is set, which (as we learned above) it will be if the arguments in the cmp were equal.

Comments

7

I think it's very late to post an answer on this question. But I can give you a better illustration on how this CMP instruction works.

When you Compare two arguments using CMP arg1, arg2

CMP instruction sets status flags according to the comparisons between the arguments. See : wikipedia's FLAGS page

The importance of CMP applies mostly in conditional code execution (Jump - See : assembly_conditions). When the processor executes a conditional-jump jcc instruction, it checks the status flags register and jumps to the target label if it meets the conditions, otherwise falls through to the next instruction.

Comments

4

cmp arg2, arg1
Performs a comparison operation between arg1 and arg2. The comparison is performed by a (signed) subtraction of arg2 from arg1, the results of which can be called Temp. Temp is then discarded.

This is factually incorrect for . It is not a subtraction of arg2 from arg1, but the other way round!
Many of the x86 instructions have 2 operands. Intel calls the leftmost operand the destination and the rightmost operand the source. Both these types of operands can refer to a register or memory, but only the source operand can additionally be an 'immediate', so a simple number.

What cmp does is actually the same as sub: calculating temp = destination - source, setting flags (OF, SF, ZF, AF, PF, CF), but not storing the result into the destination.

What does it mean "Temp is then discarded"? Where is it stored?

"Temp is then discarded" is just another way of saying the result is not stored at all.

How can I access this result of the comparison?

The only result is in the many flags, and most of the time you would perform some conditional branching following a cmp.

The wiki that you mention talks about Intel and GAS, and how they differ in the order of the arguments. I suggest you immediately forget about arg1 and arg2, but use the terminology destination (dest) and source (src). Then it is easy to remember for both Intel syntax and AT&T syntax what cmp invisibly calculates:

DESTINATION - SOURCE

1 Comment

That wikibooks page is currently a mess; it has example instructions like mov ecx, $5, like someone tried to change from AT&T mov $5, %ecx to Intel syntax but forgot to remove the $ from immediates. And didn't change the text to match. I wonder if there are any correct versions in the history it could get rolled back to... Maybe not; en.wikibooks.org/w/index.php?title=X86_Assembly/… compares current vs. a 2017 version where there was mov $5, ecx (not %ecx).
0

Here is an example in working code.

I am unpacking an ELF file, and want to know where the end of my file is in memory so I can use the rest of an assigned area as scratch memory. I can mess around with linker properties and the like that try to get a symbol at the very end, which rarely works, or I can store the largest address after copying into a register and use that when I get there.

REP MOVSB     ; RDI will have the address we of the last destination in this block
CMP R10,RDI   ; Is it bigger than our current record
JNC .nextSect ; No? Next one
MOV R10,RDI   ; Copy RDI into R10
.nextSect:
ADD R9,0x40
...
; Later on, R10 has the address of the end of the ELF file, so I know I can use it as
; a base and the rest as a protected heap

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.