Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does test and je/jne work

Okay so I started working a little with assembly. I began with the following instructions:

test       al, al
jne        0x1000bffcc

Using the debugger, I wanted the code to not jump to address 0x1000bffcc so I set a breakpoint on the jne instruction and then inverted the al register using following lldb command:

expr $al = 1

This worked well so I continued until I stumbled across the following, very similar instruction pair:

test       al, al
je         0x1000bffcc

While this looks similar, inverting the al register doesn't seem to have an affect. It keeps on jumping to address 0x1000bffcc. So I did some research and figured out that test runs a logical AND with al itself and then sets the zero flag or ZF accordingly. This leads to two questions:

  • Why did it help to invert the al register in the first example?
  • Why does it not work in the second example?
  • How can I use the debugger to make the code not jump in the second example?

Thanks a lot for your help!

like image 504
lbrndnr Avatar asked Jul 01 '15 20:07

lbrndnr


1 Answers

test    al, al
jne     0x1000bffcc

The test instruction performs a logical and of the two operands and sets the CPU flags register according to the result (which is not stored anywhere). If al is zero, the anded result is zero and that sets the Z flag. If al is nonzero, it clears the Z flag. (Other flags, such as Carry, oVerflow, Sign, Parity, etc. are affected too, but this code has no instruction testing them.)

The jne instruction alters EIP if the Z flag is not set. There is another mnemonic for the same operation called jnz.

If you let the test instruction execute and then changed al before the conditional jump instruction, the conditional jump is still going to do whatever it was going to do before altering al. That is because the value of al no longer affects the conditional jump. If you change the value before the test, then it will work as expected.

As for why changing it sometimes has an effect: It must be because the revised value of al is affecting other logic.

To use the debugger to make the instruction not jump, change the flags such that the Z flag is set. It might be called ZF, or you might have to modify the bit in the EFLAGS register. How to do this varies by the debugger and possibly its revision.

like image 72
wallyk Avatar answered Sep 22 '22 11:09

wallyk