Artificial truth

The more you see, the less you believe.

[archives] [latest] | [homepage] | [atom/rss]

Absolute value in asm
Fri 23 November 2012 — download

I was checking that a bug I reported on a previous version of r2 was fixed, and I stumbled upon this:

[0x080483cc]> pdf@sym.main
/ function: section..text (76)
| ; -------- section..text:
| 0x08048380 55 push ebp
| 0x08048381 89e5 mov ebp, esp
| 0x08048383 83e4f0 and esp, 0xfffffff0
| 0x08048386 83ec10 sub esp, 0x10
| 0x08048389 8b450c mov eax, [ebp+0xc]
| 0x0804838c c74424080a000000 mov dword [esp+0x8], 0xa
| 0x08048394 c744240400000000 mov dword [esp+0x4], 0x0
| 0x0804839c 8b4004 mov eax, [eax+0x4]
| 0x0804839f 890424 mov [esp], eax
| 0x080483a2 e8c9ffffff call dword imp.strtol
| 0x080483a7 c744240450850408 mov dword [esp+0x4], 0x8048550
| 0x080483af c7042401000000 mov dword [esp], 0x1
| 0x080483b6 89c2 mov edx, eax
| 0x080483b8 c1fa1f sar edx, 0x1f
| 0x080483bb 31d0 xor eax, edx
| 0x080483bd 29d0 sub eax, edx
| 0x080483bf 89442408 mov [esp+0x8], eax
| 0x080483c3 e898ffffff call dword imp.__printf_chk
| 0x080483c8 31c0 xor eax, eax
| 0x080483ca c9 leave
 0x080483cb c3 ret
; ------------

Can you guess what this program does ?

Original source code

This is the original source code.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[]){
    printf("%dn", abs(atoi(argv[1])));
    return 0;
}

This is where the magic lays:

sar edx, 0x1f
xor eax, edx
sub eax, edx

An abs function in 3 instructions ?! The sar instruction is like the shr one, but instead of putting a zero on the left, it will put the MSB.

eax < 0

sar edx, 0x1f ; edx = 0xFFFFFFFF = -1
xor eax, edx ; eax XOR (-1) = not eax
sub eax, edx ; eax = (eax XOR - 1) - (-1) = not eax + 1 = -eax

eax >= 0

sar edx, 0x1f ; edx = 0
xor eax, edx ; eax XOR 0 = eax
sub eax, edx ; eax = (eax XOR 0) - 0 = eax

Clever, isn't it ? This method isn't new, it's mentioned in How to Optimize for the Pentium Processor, by Agner Fog, 1996.