[英]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
. 但是,关于最后一次跳转指令
jl
。 Correct me if I'm wrong, but shouldn't there be a cmp
before the jump since it's conditional? 如果我错了,请纠正我,但是在跳转之前不应该有
cmp
,因为它是有条件的吗?
I initially thought it was based on cmp al, ah
, but jne
jumps if not equal anyway. 我最初认为它是基于
cmp al, ah
,但如果不相等的话jne
跳。
Am I missing something? 我错过了什么吗?
Consider these 3 kinds of instructions: 考虑以下3种说明:
jne
, jl
, and many more) will jump based on the current setting of one or more of the bits in the FLAGS register. jne
, jl
等等)都将根据FLAGS寄存器中一个或多个位的当前设置跳转。 cmp
instruction, there are many more instructions that will modify some of these bits in the FLAGS register (like test
, add
, and many more). cmp
指令外,还有更多指令可以修改FLAGS寄存器中的某些位(如test
, add
等等)。 mov
, push
, and many more). mov
, push
等等)。 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. jne .ver_err
根据最近的标志修改指令设置的jne .ver_err
跳转,这种指令在本例中是cmp al, ah
。
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. jl .ver
.ver基于最近的标志修改指令设置的标志位跳转,在这种情况下是inc bx
。
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 . 由于这个插入的
lea
指令不修改任何标志,因此jl .ver
.ver指令仍然根据inc bx
指令设置的flagbits跳转,因为它仍然是最新的标志修改指令 。
The jump-instructions just check the flags corresponding to the suffix. 跳转指令只检查对应于后缀的标志。 There is no need for a cmp-instruction before the jump.
在跳转之前不需要cmp指令。 In this case,
The inc-instruction just increases the register, but the flags set by the cmp-instructions are tested by the jl instruction. 在这种情况下,
inc-instruction只增加寄存器,但cmp指令设置的标志由jl指令测试。 The inc-instructions can set or reset flags. inc指令可以设置或重置标志。 Eg.
例如。 On overflow, the overflow flag is set.
溢出时,溢出标志置位。 Most processors implement cmp, by substracting the registers, but only write to the flags.
大多数处理器通过减去寄存器来实现cmp,但只写入标志。 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. 在你的情况下,它没有出现,有jl指令,因为所有不等式(包括“小于”)的情况都由jne-instruction检查,所以分支永远不会从最后一行发生。 Maybe there is missing something. 也许有遗漏的东西。 The jl tests if the operand of inc is negative. jl测试inc的操作数是否为负数。
This behaviour of the instructions is dependent of the processor you have, so x86 behaves differently to Arm and other processors. 指令的这种行为取决于您拥有的处理器,因此x86的行为与Arm和其他处理器的行为不同。 (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.) (在这种情况下,我读取了
inc
指令的页面 ,其中没有关于标志的详细信息。(C编译器需要知道,哪些标志被指令修改,它可以优化int i = a - b; if(a < b) {...}
只是减法和跳转指令。)
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. 但是你不需要专门的
cmp
指令 - 任何设置标志的指令都可以跟随一个测试标志的指令。 For example 例如
sub eax, edx
js label
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.