-2

Given this assembly code, I am having trouble translating assembly code into its equivalent C code.

   int main() {
      long int x=______;
      long int mask=0xff;
      int i,n,m;
      for(i=0;i<______;i++) {
         n=i;
         m=7-i;
         long int n8=n<<3;
         long int m8= m<<3;
         long int n_mask=mask<<n8;
         long int m_mask=mask<<m8;
         long int n_byte=((______>>n8) & ______;
         long int left_over = ______;
         x=left_over ______;
       }
    }

I was able to deduce some of the simpler blanks but am not sure how to figure out the rest.

Current Attempt:

   int main() {
      long int x=7;
      long int mask=0xff;
      int i,n,m;
      for(i=0;i<4;i++) {
         n=i;
         m=7-i;
         long int n8=n<<3;
         long int m8= m<<3;
         long int n_mask=mask<<n8;
         long int m_mask=mask<<m8;
         long int n_byte=((______>>n8) & ______;
         long int left_over = ______;
         x=left_over ______;
       }
    }
  • Looks like `n8=n<<3;` is being done with an LEA (with a scale factor of 8) to copy-and-shift. Of course `n` is optimized away so it's just `n8 = i*8`, with no copying to a separate register to actually materialize an `n` variable before the shift. Looks like it was compiled with `gcc -Og` or `gcc -O1`, because it didn't use the `xor %edx,%edx` peephole for setting EDX=0 before falling into the loop, instead using a mov-immediate of `$0`. – Peter Cordes Feb 02 '19 at 04:26
  • It is compiled with gcc -O1. Any idea what the rest of the blanks are? – John Larkos Feb 02 '19 at 04:46
  • Oh that's weird, I wonder what version of gcc would print `sarq %ecx, ...` instead of `%cl`? x86 variable-count right shifts take the count in CL, not ECX. (Not that it matters; they mask the count to only look at the low 5 or 6 bits anyway.) But even the oldest gcc and clang on the Godbolt compiler explorer (https://godbolt.org/z/WMC9Ke) print the normal ` sarq %cl, %rax`. Either this is from an even older compiler, or it's hand-edited. Anyway, looks like a mess of code to wade through, but I don't see any obvious problem with figuring out which variable is being shifted and masked. – Peter Cordes Feb 02 '19 at 05:02
  • Where are you stick? Post a commented version of the asm with what you have so far labeling registers with C variables. `x=left_over ______;` is weird, though. I guess the previous line must declare and initialize it, because `left_over` doesn't appear anywhere else in the source, and that's the only place we can declare a new variable. Presumably the last blank is an operator and some other variable. Presumably `|` for the `or` instruction into RSI that's done last in the asm. – Peter Cordes Feb 02 '19 at 05:05
  • That is exactly particularly where I am stuck. I don't have much of an issue with the assembly commands themselves but having trouble figuring out what values are stored in which register so I can trace the commands. – John Larkos Feb 02 '19 at 05:47
  • 3
  • 3
    [Discourage screenshots of code and/or errors](https://meta.stackoverflow.com/q/303812/995714) – phuclv Feb 02 '19 at 08:49
  • 1
    I downvoted because your assembly code was posted as a picture. – fuz Feb 02 '19 at 10:56

1 Answers1

0

having trouble figuring out what values are stored in which register so I can trace the commands.

Start outside the loop.

0xff = 255 so R9 is mask.

GCC hoists the 7 out of the loop, and does 7-i with mov %r10d, %edi / sub %edx, %edi, so we know at that point m = EDI. (And that r10d is just holding 7, not x, because there's also a movabs to init another reg.)

The only other variable initialization outside the loop that's un-accounted for is x, so RSI = x.

It goes on from there. From tracing m, it goes on from there.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847