1

I need help interpreting this assembly code.

Given that it resembles a triply-nested if-block. Let num=0x708, flag=-1;

The first condition is straightforward, if(num& 0x3 == 0). However, the next second and third conditions are lengthy; the operations are the same, but the numbers are different. Is there anything meaningful these two conditions do, or are they just a litany of random commands?

<+0>:   push %rbp 
<+1>:   mov  %rsp,%rbp 
<+4>:   movl $0x708,-0x8(%rbp) 
<+11>:  movl $0xffffffff,-0x4(%rbp) 
<+18>:  mov  -0x8(%rbp),%eax 
<+21>:  and  $0x3,%eax 
<+24>:  test %eax,%eax                       <====first condition
<+26>:  jne  <main+128> 
<+28>:  mov  -0x8(%rbp),%ecx 
<+31>:  mov  $0x51eb851f,%edx 
<+36>:  mov  %ecx,%eax 
<+38>:  imul %edx 
<+40>:  sar  $0x5,%edx 
<+43>:  mov  %ecx,%eax 
<+45>:  sar  $0x1f,%eax 
<+48>:  sub  %eax,%edx 
<+50>:  mov  %edx,%eax 
<+52>:  imul $0x64,%eax,%eax 
<+55>:  sub  %eax,%ecx 
<+57>:  mov  %ecx,%eax 
<+59>:  test %eax,%eax                    <====second condition
<+61>:  jne  <main+119> 
<+63>:  mov  -0x8(%rbp),%ecx 
<+66>:  mov  $0x51eb851f,%edx 
<+71>:  mov  %ecx,%eax 
<+73>:  imul %edx 
<+75>:  sar  $0x7,%edx 
<+78>:  mov  %ecx,%eax 
<+80>:  sar  $0x1f,%eax 
<+83>:  sub  %eax,%edx 
<+85>:  mov  %edx,%eax 
<+87>:  imul $0x190,%eax,%eax 
<+93>:  sub  %eax,%ecx 
<+95>:  mov  %ecx,%eax 
<+97>:  test %eax,%eax                        <========third condition
<+99>:  jne  <main+110>

…

zx485
  • 28,498
  • 28
  • 50
  • 59
thegoodhunter-9115
  • 317
  • 1
  • 3
  • 15
  • 1
    The other two tests are `num % 100 == 0` and `num % 400 == 0` – harold Mar 01 '20 at 21:21
  • Thank you, @Harold. Could you explain (roughly) how you got that? – thegoodhunter-9115 Mar 01 '20 at 21:26
  • 2
    Honestly I have not veried it, but the pattern of: multiply by weird constant, take the `edx`-output and shift it right and that `sar` by 31 to compensate for negative numbers is a classic divide-by-constant pattern. I didn't look too hard at the specific constant though. Then multiplying by a constant again and subtracting, is the classic `x - (x / c) * c` pattern to do a remainder-by-constant. – harold Mar 01 '20 at 21:30
  • I understand it a bit better now (I'm new to Assembly/Programming). If you could answer a few questions: What do you mean to compensate for negative numbers? What does imul $0x190,%eax,%eax do (I see that 0x190=0d400)? and Where do we divide in the code? Thank you again. – thegoodhunter-9115 Mar 01 '20 at 21:40
  • 2
    @harold: Perhaps this function determines whether a year number is a leap year? – ecm Mar 01 '20 at 22:02
  • [Why does GCC use multiplication by a strange number in implementing integer division?](https://stackoverflow.com/q/41183935) explains the unsigned case. Not sure if there's a good canonical about how SAR is used to get correct rounding for negative dividends, correcting for an off-by-one – Peter Cordes Mar 01 '20 at 22:14

0 Answers0