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.