简体   繁体   中英

Is it possible to use a conditional jump in assembly without a `cmp` first?

So I'm reading through some assembly source code for learning purposes and came across something very strange (or I may just be a newb):

.ver:
    mov al, [redoxfs.header + Header.version +  bx]
    mov ah, [.version + bx]
    cmp al, ah
    jne .ver_err
    inc bx
    jl .ver

So in this sub-label we have two jump instructions.

However, about the last jump instruction jl . Correct me if I'm wrong, but shouldn't there be a cmp before the jump since it's conditional?

I initially thought it was based on cmp al, ah , but jne jumps if not equal anyway.

Am I missing something?

Consider these 3 kinds of instructions:

  • All of the conditional jumps (like jne , jl , and many more) will jump based on the current setting of one or more of the bits in the FLAGS register.
  • Besides the cmp instruction, there are many more instructions that will modify some of these bits in the FLAGS register (like test , add , and many more).
  • And then there are lots of instructions that don't modify any of the flags (like mov , push , and many more).

Examples

cmp al, ah
jne .ver_err

The jne .ver_err jumps based on the flagbits set by the most recent flags modifying instruction which is cmp al, ah in this case.

inc bx
jl .ver

The jl .ver jumps based on the flagbits set by the most recent flags modifying instruction which is inc bx in this case.

inc bx
lea si, [si+1]
jl .ver

Since this interjected lea instruction does not modify any flags, the jl .ver instruction still jumps based on the flagbits set by the inc bx instruction because that's still the most recent flags modifying instruction .

The jump-instructions just check the flags corresponding to the suffix. There is no need for a cmp-instruction before the jump. In this case, The inc-instruction just increases the register, but the flags set by the cmp-instructions are tested by the jl instruction. The inc-instructions can set or reset flags. Eg. On overflow, the overflow flag is set. Most processors implement cmp, by substracting the registers, but only write to the flags. So the sub-instruction sets the same flags and can also be used for a comparison. Multiple branches after each other are also allowed, where the flags are rechecked by the jump-instructions.

cmp eax, ecx
jl lbl_less
je lbl_equal
jg lbl_greater

You can also explicitly set flags, eg. in a called function, which can be checked later by the jump-instructions.

stc ;; set carry-flag

;; instructions, which not unintentionally change the carry-flag

clc ;; clear carry-flag

;; ...

jc lbl_carry_is_set ;; check and jump

In your case it does not make sence, that there is the jl-instruction, because all cases of inequality(which includes "less than") are checked by the jne-instruction, so the branch never occurs from the last line. Maybe there is missing something. The jl tests if the operand of inc is negative.

This behaviour of the instructions is dependent of the processor you have, so x86 behaves differently to Arm and other processors. (In this case, I read a page of the inc instruction where there is no much detail about the flags. (A C-compiler needs to know, which flags are modified by the instructions, it can optimize int i = a - b; if(a < b) {...} to just a substraction- and a jump-instruction.)

You can have as many instructions as you like between the instruction that sets the flags, and the instruction thats tests them, so long as none of them affect the flags you want to test, and detailed knowledge of the instructions and/or a good reference are essential.

cmp eax,edx
xchg eax,edx
jne label

But you don't need a cmp instruction specifically - any instruction that sets flags can then be followed by an instruction that tests the flags. For example

sub eax, edx
js label

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM