Reputation: 1013
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?
Upvotes: 6
Views: 8206
Reputation: 1856
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.)
Upvotes: 3
Reputation: 39446
Consider these 3 kinds of instructions:
jne
, jl
, and many more) will jump based on the current setting of one or more of the bits in the FLAGS register. cmp
instruction, there are many more instructions that will modify some of these bits in the FLAGS register (like test
, add
, and many more).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.
Upvotes: 8
Reputation: 34585
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
Upvotes: 3