xorpd has some riddle-like pieces of assembly code here. In this post, I’ll analyze this one.

I present to you the riddle number 0x02:

neg      rax
sbb rax,rax
neg rax

In order to understand this one we first need to understand neg and sbb instructions. Let’s check Intel’s manuals:

Integer Subtraction with Borrow (aka sbb) definition from Intel’s manual:

Adds the source operand (second operand) and the carry (CF) flag, and subtracts the result from the destination operand (first operand). The result of the subtraction is stored in the destination operand

DEST ← (DEST — (SRC + CF));

Two’s Complement Negation (aka neg) definition from Intel’s manual:

Replaces the value of operand (the destination operand) with its two’s complement. (This operation is equivalent to subtracting the operand from 0.)

IF DEST = 0
THEN CF ← 0;
ELSE CF ← 1;
FI;
DEST ← [– (DEST)]

Now you may ask, how’s the two’s complement obtained? It’s obtained just by flipping every bit and then adding 1 to the result. Here are some examples:

00110101 ==(flip)==> 11001010 ==(+1)==> 11001011
11001011 is the 2’s complement of 00110101
11110000 ==(flip)==> 00001111 ==(+1)==> 00010000
00010000 is the 2’s complement of 11110000

Now that we grasp what each instruction does let’s analyze the code line by line

Line 1: neg rax

This computes the two’s complement, places the result into rax and updates the Carry Flag (CF) accordingly.

Example 1: Suppose the original value from rax on line 1 was 101neg rax ; rax is now = !rax+1 = (!101)+1 = 010+1 = 011
; CF=1

Example 2: Suppose the original value from rax on line 1 was 000
neg rax ; rax is now = !rax+1 = (!000)+1 = 111+1 = 000
; CF=0

Line 2: sbb rax, rax

This op performs subtraction between rax and itself + the CF (which is 0 if the original value from rax was 0, or 1 otherwise).

Following Example 1 (original rax value was 101):sbb rax, rax ; This can be expressed as:
; 1. 011 - (011+CF) CF=1 in this case, from prev op
; 2. 011 - (011+1) <--|
; 3. 011 - 100
; 4. 111 A borrow occurred here

Following Example 2 (original rax value was 000):
sbb rax, rax ; This can be expressed as:
; 1. 000 - (000+CF) CF=0 in this case, from prev op
; 2. 000 - (000+0) <--|
; 3. 000 - 000
; 4. 000

Line 3: neg rax

Same as in line 1, of course, but just with updated values from previous ops:

Following Example 1 (original rax value was 101):
neg rax ; rax is now = !rax+1 = (!111)+1 = 000+1 = 001

Following Example 2 (original rax value was 000):
neg rax ; rax is now = !rax+1 = (!000)+1 = 111+1 = 000

Conclusion

As a final conclusion, we can say that this piece of code sets rax to 0 if its original value was 0 or to 1 if it was otherwise. I can imagine this to be a sort of integer to boolean conversion. In a high-level programming language this could be expressed as:

func foo(n *int) bool {
return *n != 0
}

Written by

Syscall59 — by Alan Vivona

Shellcode for the masses

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just \$5/month. Upgrade