1

What does it mean when there's no CMP instruction before before a JNE statement?

 0x0000000000401114 <+64>:  add    %eax,%ecx
   0x0000000000401116 <+66>:    cltq   
   0x0000000000401118 <+68>:    mov    0x4026e0(,%rax,4),%eax
   0x000000000040111f <+75>:    sub    $0x1,%edx
   0x0000000000401122 <+78>:    jne    0x401114 <phase_5+64>

What am I comparing to?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Kamerov
  • 109
  • 1
  • 4
  • 11
  • the conditional jumps are individual instructions, just checking current state of CPU (flags, with some exception like `jcxz` and `loop` if you consider `loop` conditional jump). The CPU has its flags all the time (it's just another register). So the `JNE` is comparing if ZF==0, then jumps. Semantically the last instruction modifying ZF ahead of that jump is `sub`, and if you will read description of `cmp`, you will see the `cmp` is also `sub` (with "discard result" feature), so you are comparing `edx--` with `1`, and after the jump will not branch, the `edx == 0` (on `<+80>`). – Ped7g Feb 13 '18 at 08:03
  • [Does a JE must follow directly to an CMP?](https://reverseengineering.stackexchange.com/q/4436/2563) – phuclv Apr 30 '21 at 03:00

3 Answers3

3

cmp edx, 1 changes the flags exactly like sub edx, 1, only it doesn't update edx. This means that instead of doing a cmp and sub in a loop, you only need to do sub

C_Elegans
  • 1,113
  • 8
  • 15
2

JNE instruction is used to test and jump if ZF (zero flag) is zero

SUB instruction will set ZF flag to 1 if $0x1 and %edx are equal, and 0 otherwise

Iłya Bursov
  • 23,342
  • 4
  • 33
  • 57
  • 2
    Just to clarify, while `cmp` sets flags, so do a number of other instructions (add, sub, inc, dec, test, bt, and many others). These set the same flags. When possible, optimizing compilers like to take advantage of this fact when generating code. For example, if you have a loop that runs 10 times, instead of setting a register to 1 and incrementing it to 10, doing `cmp ecx, 10` in each loop, compilers will set the register to 10, then at the bottom of the loop they do `dec ecx ; jnz top` (at least if the loop doesn't actually use the value of ecx). It's just one of the many tricks for x86 asm. – David Wohlferd Feb 13 '18 at 03:42
2

SUB (like most x86 integer instructions) sets flags based on the result, i.e. ZF will be set if EDX became zero.

Your disassembler showed the mnemonic as JNE, but the JNZ synonym has the more appropriate semantic meaning here, because you really care more about EDX becoming zero after the SUB.

It's easier not to think of it as a comparison against 1, but rather as the bottom of a
do {} while(--edx); loop,

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847