Average_guy
Average_guy

Reputation: 569

Trouble understanding this assembly code

I have an exam comming up, and I'm strugling with assembly. I have written some simple C code, gotten its assembly code, and then trying to comment on the assembly code as practice. The C code:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char const *argv[])
{
   int x = 10;
   char const* y = argv[1];

   printf("%s\n",y );

   return 0;
}

Its assembly code:

   0x00000000000006a0 <+0>: push   %rbp                   # Creating stack
   0x00000000000006a1 <+1>: mov    %rsp,%rbp              # Saving base of stack into base pointer register
   0x00000000000006a4 <+4>: sub    $0x20,%rsp             # Allocate 32 bytes of space on the stack
   0x00000000000006a8 <+8>: mov    %edi,-0x14(%rbp)       # First argument stored in stackframe
   0x00000000000006ab <+11>:    mov    %rsi,-0x20(%rbp)   # Second argument stored in stackframe
   0x00000000000006af <+15>:    movl   $0xa,-0xc(%rbp)    # Value 10 stored in x's address in the stackframe
   0x00000000000006b6 <+22>:    mov    -0x20(%rbp),%rax   # Second argument stored in return value register
   0x00000000000006ba <+26>:    mov    0x8(%rax),%rax     # ??
   0x00000000000006be <+30>:    mov    %rax,-0x8(%rbp)    # ??
   0x00000000000006c2 <+34>:    mov    -0x8(%rbp),%rax    # ??
   0x00000000000006c6 <+38>:    mov    %rax,%rdi          # Return value copied to 1st argument register - why??
   0x00000000000006c9 <+41>:    callq  0x560              # printf??
   0x00000000000006ce <+46>:    mov    $0x0,%eax          # Value 0 is copied to return register
   0x00000000000006d3 <+51>:    leaveq                    # Destroying stackframe
   0x00000000000006d4 <+52>:    retq                      # Popping return address, and setting instruction pointer equal to it

Can a friendly soul help me out wherever I have "??" (meaning I don't understand what is happening or I'm unsure)?

Upvotes: 0

Views: 1259

Answers (2)

Giuseppe Cotugno
Giuseppe Cotugno

Reputation: 110

I will try to make a guess:

mov    -0x20(%rbp),%rax   # retrieve argv[0]
mov    0x8(%rax),%rax     # store argv[1] into rax
mov    %rax,-0x8(%rbp)    # store argv[1] (which now is in rax) into y
mov    -0x8(%rbp),%rax    # put y back into rax (which might look dumb, but possibly it has its reasons)
mov    %rax,%rdi          # copy y to rdi, possibly to prepare the context for the printf

When you deal with assembler, please specify which architecture you are using. An Intel processor might use a different set of instructions from an ARM one, the same instructions might be different or they might rely on different assumptions. As you might know, optimisations change the sequence of assembler instructions generated by the compiler, you might want to specify whether you are using that as well (looks like not?) and which compiler you are using as everyone has its own policy for generating assembler.

Maybe we will never know why the compiler must prepare the context for printf by copying from rax, it could be a compiler's choice or an obligation imposed by the specific architecture. For all those annoying reasons, most of people prefer to use a "high level language" such as C, so that the set of instructions is always right although it might look very dumb for a human (as we know computers are dumb by design) and not always the most choice, that's why there are still many compilers around.

I can give you two more tips:

  1. you IDE must have a way to interleave assembler instructions with C code, and to single step within the assembler. Try to find it out and explore it yourself

  2. the IDE should also have a function to explore the memory of your program. If you find that try to enter the 0x560 address and look were it will lead you. It is very likely that that will be the entry point of your printf

I hope that my answer will help you work it out, good luck

Upvotes: 2

j31d0
j31d0

Reputation: 151

   0x00000000000006ba <+26>:    mov    0x8(%rax),%rax     # get argv[1] to rax
   0x00000000000006be <+30>:    mov    %rax,-0x8(%rbp)    # move argv[1] to local variable
   0x00000000000006c2 <+34>:    mov    -0x8(%rbp),%rax    # move local variable to rax (for move to rdi)
   0x00000000000006c6 <+38>:    mov    %rax,%rdi          # now rdi has argv[1]
   0x00000000000006c9 <+41>:    callq  0x560              # it is puts (optimized)

Upvotes: 5

Related Questions