2

I'm trying to understand some disassembled code, but I can't understand what's going on here. Can you explain what it does?

sub     ecx, edi    
sar     edx, 1
mov     eax, 2AAAAAABh
imul    ecx
mov     eax, edx
shr     eax, 31
add     eax, edx
test    eax, eax
jle     ...

ecx, edx and edi contains some kind of input values for this code.

I can only assume that the pair of last two lines may work as something like if(eax <= 0) goto ..., but I'm not sure.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Nyan Cat
  • 303
  • 1
  • 5
  • 14
  • `ecx`, `edx`, `edi`, and `eax` are [registers](https://en.wikipedia.org/wiki/X86_assembly_language). The `test` instruction sets `cflags` which the conditional instructions like `jle` use. – Jason Oct 09 '14 at 05:54
  • I mean, that `ecx`, `edx` and `edi` registers contains input values for this code block. – Nyan Cat Oct 09 '14 at 05:56
  • `ecx` is generally a loop count register, and `edi` is a destination register, so it's probably looping over an array. You would need to determine what each of the registers is being used for to determine what the code is actually doing though. – Jason Oct 09 '14 at 06:09
  • 1
    Do you have any idea of what the `mov eax, 2AAAAAABh` instruction is about ? I'm not seeing that as making immediate sense. – User.1 Oct 09 '14 at 06:11
  • This constant used in code few thousand times. And I haven't any idea, what it means. Maybe, it is some kind of obfuscation or math optimization. – Nyan Cat Oct 09 '14 at 09:04
  • More context about what the program does would be helpful. – Dwayne Towell Oct 09 '14 at 15:32

3 Answers3

3

2AAAAAAB is a "magic number". The sequence

MOV    EAX, 2AAAAAABh
IMUL   dividend
MOV    EAX, dividend
SHR    EAX, 31
ADD    EDX, EAX

is this signed division without using IDIV:

EDX = dividend/6

The instruction sar edx, 1 is useless, since EDX will be overwritten by imul ecx. In C the posted sequence can written as

if ((ECX-EDI)/6 > 0) { ... } else ("jle") { ... }.

rkhb
  • 14,159
  • 7
  • 32
  • 60
  • Full details about multiplicative inverses: [Why does GCC use multiplication by a strange number in implementing integer division?](https://stackoverflow.com/questions/41183935/why-does-gcc-use-multiplication-by-a-strange-number-in-implementing-integer-divi). This question isn't *quite* a duplicate, because it's also asking about the branch, and has the mysterious dead `sar`. Very surprising to that in decompiled code; possibly it's not compiler-generated or was mis-copied. – Peter Cordes Feb 04 '18 at 13:06
1

the code is a form of an optimized division, the constant used in the code is a Wagstaff prime,

rcd
  • 112
  • 1
  • 4
0

I think it is checking for overflow of a calculation for unknown purposes.

sub  ecx,edi       ; ecx = ??? no idea where these come from or what they mean

sar  edx,1         ; edx changed but value is lost, as are flags, no idea why this is done

mov  eax,2AAAAAABh ; eax = 715827883, no idea why this number is important
imul ecx           ; edx:eax = (original ecx-edi) * 715827883

mov  eax,edx       ; eax = high-dword of product
shr  eax,31        ; eax = high-bit of high-dword of product
add  eax,edx       ; eax = high-dword of product + high-bit of high-dword of product
                   ; assuming 0 <= ecx < ~10, eax will be zero if the result did not carry into edx
                   ; assuming ~-10 < ecx < 0, eax will be zero if the result did not carry into edx
                   ; therefore, |ecx|<~10, eax = overflow-from-multiplication

test eax,eax 
jle ...            ; taken if eax=0 or SF=OF

I'm not sure what the significance of the "sign flag = overflow flag" part means. It may not be possible to occur for small values of ecx.

Dwayne Towell
  • 8,154
  • 4
  • 36
  • 49