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 if a bug I reported on a previous version of r2 was fixed and stumbled upon this:

[0x080483cc]> pdf@sym.main
/ function: section..text (76)
| ; -------- section..text:
| 0x08048380  push ebp
| 0x08048381  mov ebp, esp
| 0x08048383  and esp, 0xfffffff0
| 0x08048386  sub esp, 0x10
| 0x08048389  mov eax, [ebp+0xc]
| 0x0804838c  mov dword [esp+0x8], 0xa
| 0x08048394  mov dword [esp+0x4], 0x0
| 0x0804839c  mov eax, [eax+0x4]
| 0x0804839f  mov [esp], eax
| 0x080483a2  call dword imp.strtol
| 0x080483a7  mov dword [esp+0x4], 0x8048550
| 0x080483af  mov dword [esp], 0x1
| 0x080483b6  mov edx, eax
| 0x080483b8  sar edx, 0x1f
| 0x080483bb  xor eax, edx
| 0x080483bd  sub eax, edx
| 0x080483bf  mov [esp+0x8], eax
| 0x080483c3  call dword imp.__printf_chk
| 0x080483c8  xor eax, eax
| 0x080483ca  leave
|   0x080483cb  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.

If 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

If 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.