无法理解这个汇编代码

时间:2018-01-17 12:06:10

标签: c assembly x86

我正在考试,我正忙着装配。我编写了一些简单的C代码,获得了汇编代码,然后尝试将汇编代码作为实践进行评论。 C代码:

#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;
}

其汇编代码:

   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

友善的灵魂可以帮助我,无论我在哪里“??” (意思是我不明白发生了什么或者我不确定)?

2 个答案:

答案 0 :(得分:4)

   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)

答案 1 :(得分:2)

我会试着猜一下:

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

当您处理汇编程序时,请指定您正在使用的架构。英特尔处理器可能使用来自ARM的不同指令集,相同的指令可能不同,或者它们可能依赖于不同的假设。您可能知道,优化会更改编译器生成的汇编程序指令的顺序,您可能希望指定是否也使用它(看起来不是?)以及您使用的编译器,因为每个人都有自己的生成汇编程序的策略

也许我们永远不会知道为什么编译器必须通过从rax复制来为printf准备上下文,它可能是编译器的选择或特定架构强加的义务。出于所有这些恼人的原因,大多数人更喜欢使用高级语言&#34;比如C,所以指令集始终是正确的,虽然对于人类来说可能看起来很愚蠢(因为我们知道计算机在设计上是愚蠢的)而且并不总是最多的选择,这就是为什么还有很多编译器的原因周围。

我可以再给你两个提示:

  1. IDE必须能够将汇编程序指令与C代码交错,并在汇编程序中单步执行。试着找出来并自己探索

  2. IDE还应具有探索程序内存的功能。如果你发现尝试输入0x560地址,那么它会引导你。这很可能是printf

  3. 的切入点

    我希望我的回答可以帮助你解决问题,祝你好运