Here is a simple C program:
void main()
{
unsigned char number1 = 4;
unsigned char number2 = 5;
if (number1 < number2)
{
number1 = 0;
}
}
So here we are comparing two numbers. In assembly it will be done using cmp. cmp works by subtracting one operand from other.
Now how cmp is subtracting operands? Is it subtracting 1st operand from 2nd or vice versa? In any case, this should go like this:
case # 1:
4 - 5 = (0000 0100 - 0000 0101) = (0000 0100 + 1111 1010 + 1) = (0000 0100 + 1111 1011)
= 1111 1111 = -1
So since the sign bit = 1 so SF should be 1.
No carry, so CF should be = 0.
case # 2:
5 - 4 = (0000 0101 - 0000 0100) = (0000 0101 + 1111 1011 + 1)
= (0000 0101 + 1111 1100) = 1 0000 0001
so here, CF should be = 1
since result is positive, SF should be = 0
Now I compile and run program (linux x86_64, gcc, gdb), place a breakpoint after cmp instruction to see register states.
Breakpoint hit after cmp:
Breakpoint 2, 0x0000000000400509 in main ()
(gdb) disassemble
Dump of assembler code for function main:
0x00000000004004f6 <+0>: push %rbp
0x00000000004004f7 <+1>: mov %rsp,%rbp
0x00000000004004fa <+4>: movb $0x4,-0x2(%rbp)
0x00000000004004fe <+8>: movb $0x5,-0x1(%rbp)
0x0000000000400502 <+12>: movzbl -0x2(%rbp),%eax
0x0000000000400506 <+16>: cmp -0x1(%rbp),%al
=> 0x0000000000400509 <+19>: jae 0x40050f <main+25>
0x000000000040050b <+21>: movb $0x0,-0x2(%rbp)
0x000000000040050f <+25>: pop %rbp
0x0000000000400510 <+26>: retq
End of assembler dump.
Register dump after cmp has been executed:
(gdb) info reg
rax 0x4 4
rbx 0x0 0
rcx 0x0 0
rdx 0x7fffffffe608 140737488348680
rsi 0x7fffffffe5f8 140737488348664
rdi 0x1 1
rbp 0x7fffffffe510 0x7fffffffe510
rsp 0x7fffffffe510 0x7fffffffe510
r8 0x7ffff7dd4dd0 140737351863760
r9 0x7ffff7de99d0 140737351948752
r10 0x833 2099
r11 0x7ffff7a2f950 140737348041040
r12 0x400400 4195328
r13 0x7fffffffe5f0 140737488348656
r14 0x0 0
r15 0x0 0
rip 0x400509 0x400509 <main+19>
eflags 0x297 [ CF PF AF SF IF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
(gdb)
So we can see that after cmp has been executed, both CF=1, SF=1.
So the actual resulted flags (CF=1 & SF=1) are not equal to flags we calculated in
Case # 1 (CF=0 & SF=1) or case # 2 (CF=1 & SF=0)
Whats happening then? How cmp is actually setting the flags?