4

I've been trying to decompile the following asm snippet(that's all I have):

55                      push   %rbp
48 89 e5                mov    %rsp,%rbp
48 81 ec d0 00 00 00    sub    $0xd0,%rsp
64 48 8b 04 25 28 00    mov    %fs:0x28,%rax
00 00 
48 89 45 f8             mov    %rax,-0x8(%rbp)
31 c0                   xor    %eax,%eax
48 c7 85 30 ff ff ff    movq   $0x0,-0xd0(%rbp)
00 00 00 00 
48 8d b5 38 ff ff ff    lea    -0xc8(%rbp),%rsi
b8 00 00 00 00          mov    $0x0,%eax
ba 18 00 00 00          mov    $0x18,%edx
48 89 f7                mov    %rsi,%rdi
48 89 d1                mov    %rdx,%rcx
f3 48 ab                rep stos %rax,%es:(%rdi)
48 8b 15 19 06 20 00    mov    0x200619(%rip),%rdx
48 8d 85 30 ff ff ff    lea    -0xd0(%rbp),%rax
be ce 0f 40 00          mov    $0x400fce,%esi
48 89 c7                mov    %rax,%rdi
b8 00 00 00 00          mov    $0x0,%eax
e8 4e fc ff ff          callq  4008a0 <sprintf@plt>

Here is my attempt:

char buf[192] = {0};
sprintf(buf, "hello %s", name);

I've compiled this with gcc 4.8.5, and it gave me:

55                      push   %rbp
48 89 e5                mov    %rsp,%rbp
48 81 ec d0 00 00 00    sub    $0xd0,%rsp
64 48 8b 04 25 28 00    mov    %fs:0x28,%rax
00 00 
48 89 45 f8             mov    %rax,-0x8(%rbp)
31 c0                   xor    %eax,%eax
48 8d b5 30 ff ff ff    lea    -0xd0(%rbp),%rsi
b8 00 00 00 00          mov    $0x0,%eax
ba 18 00 00 00          mov    $0x18,%edx
48 89 f7                mov    %rsi,%rdi
48 89 d1                mov    %rdx,%rcx
f3 48 ab                rep stos %rax,%es:(%rdi)
48 8b 15 14 14 20 00    mov    0x201414(%rip),%rdx
48 8d 85 30 ff ff ff    lea    -0xd0(%rbp),%rax
be 2e 10 40 00          mov    $0x40102e,%esi
48 89 c7                mov    %rax,%rdi
b8 00 00 00 00          mov    $0x0,%eax
e8 cb fb ff ff          callq  4008a0 <sprintf@plt>

I'm struggling to figure out why this exists:

movq   $0x0,-0xd0(%rbp)

and also the subsequent usage of -0xd0(%rbp) as a pointer for the argument to sprintf. I'm puzzled because the rep stos begin at -0xc8(%rbp) and not -0xd0(%rbp).

This is probably compiler specific, but still I'm curious what could possibly be the original code that produced that asm.

randy
  • 53
  • 4
  • Your original code looks like it came from a compiler with optimization disabled. [No self-respecting compiler would ever emit `mov $0x0,%eax` instead of `xor %eax, %eax` there](http://stackoverflow.com/questions/33666617/what-is-the-best-way-to-set-a-register-to-zero-in-x86-assembly-xor-mov-or-and/33668295#33668295), especially since eax was already zeroed from two instructions ago. The point is, don't expect the code to be sane, and do expect it to sync everything to memory after every C statement instead of keeping stuff in registers. (So a debugger can change variables). – Peter Cordes Aug 25 '16 at 20:25

1 Answers1

1

I imagine something like:

char buf[192] = {0, 0, 0, 0, 0, 0, 0, 0};
sprintf(buf + 8, "hello %s", name);

... would give you that output.

The movq instruction you refer to stores 0 (an 8-byte quantity) at the beginning of an array. The -0xc8(%rbp) comes from copying a string to an offset within the array.

davmac
  • 20,150
  • 1
  • 40
  • 68
  • Why would the compiler use a movq to store a 0 at the beginning? I suppose it would do that if the array is `char buf[8]`, but I'm assuming that the array here is larger than 8 bytes and hence it would just use the rep stos to zero out the whole array. Unless you're referring to an explicit `buf[0] = 0`, which shouldn't be the case since this results in a `movb` instead of `movq` – randy Aug 25 '16 at 16:57
  • @randy: Are you sure you're using the same version of gcc as the one that made the un-optimized code you're trying to replicate? Caring this much about un-optimized code honestly sounds like a huge waste of time to me. But yes, it does look like the compiler did the first 8 bytes of initialization with a movq, and the rest with rep stos. – Peter Cordes Aug 25 '16 at 20:32