【问题标题】:unable to understand the base pointer calculation in assembly code [closed]无法理解汇编代码中的基指针计算[关闭]
【发布时间】:2017-07-06 14:18:43
【问题描述】:

我试图通过反汇编程序来理解以下函数的汇编代码。我不明白为什么所有的操作都是相对于基指针的。

  1. 为什么rcxrdx的寄存器值被移动到偏移10和18的内存位置? (mov 0x10(%rbp),%raxmov %rdx,0x18(%rbp))。

  2. 为什么返回值存储在 mov %rax,-0x8(%rbp)


long absdiff(long x, long y)
{
    long result;
    if (x>y)
        result = x-y;
    else
        result = y-x;
    return result;
}
0x00000001004010e0 <+0>:     push   %rbp
0x00000001004010e1 <+1>:     mov    %rsp,%rbp
0x00000001004010e4 <+4>:     sub    $0x10,%rsp
0x00000001004010e8 <+8>:     mov    %rcx,0x10(%rbp)
0x00000001004010ec <+12>:    mov    %rdx,0x18(%rbp)
0x00000001004010f0 <+16>:    mov    0x10(%rbp),%rax
0x00000001004010f4 <+20>:    cmp    0x18(%rbp),%rax
0x00000001004010f8 <+24>:    jle    0x100401108 <absdiff+40>
0x00000001004010fa <+26>:    mov    0x10(%rbp),%rax
0x00000001004010fe <+30>:    sub    0x18(%rbp),%rax
0x0000000100401102 <+34>:    mov    %rax,-0x8(%rbp)
0x0000000100401106 <+38>:    jmp    0x100401114 <absdiff+52>
0x0000000100401108 <+40>:    mov    0x18(%rbp),%rax
0x000000010040110c <+44>:    sub    0x10(%rbp),%rax
0x0000000100401110 <+48>:    mov    %rax,-0x8(%rbp)
0x0000000100401114 <+52>:    mov    -0x8(%rbp),%rax
0x0000000100401118 <+56>:    add    $0x10,%rsp
0x000000010040111c <+60>:    pop    %rbp
0x000000010040111d <+61>:    retq

【问题讨论】:

  • 为什么要减去 10 个字节............0x10=16.....
  • 您应该开始识别xy 在汇编代码中的表示方式。为什么您希望从堆栈指针中减去 8?提示:这是编译为 64 位程序。
  • 我建议在编译时启用优化。该程序集将大大更短且更易于理解。
  • @EOF 更短:是的,更容易理解:不一定。
  • @MichaelWalz 我发现它本质上总是更具可读性。然而,这可能对我来说是相当具体的。

标签: c assembly stack x86-64


【解决方案1】:

1) 为什么是sub $0x10, %rsp

它实际上是减去 16 个字节,换句话说,它为两个“长”参数腾出空间。尝试打印'sizeof(long)',我很确定你会在你所在的机器上得到'8'作为答案。

2) 为什么将寄存器值移动到内存中?

这也是计算机将寄存器“​​rcx”和“rdx”中的两个长值加载到它在“1)”中创建的内存空间的地方。 0x10 和 0x18 相差 8 个字节。

3)为什么返回值存储在mov %rax,-0x8(%rbp)中?

它是临时存储的,因为在离开函数之前,%rax 寄存器用于其他一些计算。因此,如果它没有被保存,它就会被覆盖,你可以看到在这些计算完成后,值又被加载到 rax 中。

mov%rax,-0x8(%rbp) <--- saving
jmp    0x100401114 <absdiff+52>
...
mov    %rax,-0x8(%rbp)
-0x8(%rbp),%rax" < -- retrieving

建议

我很确定你会发现这个链接真的很有帮助:

https://www.recurse.com/blog/7-understanding-c-by-learning-assembly

【讨论】:

  • 请努力并正确格式化您的答案。然后你会得到我的支持。
  • 那里!谢谢你的吐槽,真的很有用。和平! (y)
  • 当它 (rbp) - 8 时,这不会覆盖内存位置中已经存在的任何内容吗?还是该位置已分配给该功能? mov %rax,-0x8(%rbp)
  • 对于 #2,您是在解释 什么 它在做什么,但实际上并没有回答 为什么。原因是因为这是未优化的代码,每个中间结果都会溢出到内存中,而不是保存在寄存器中。 #3 也是一样:绝对没有理由存储和重新加载 RAX。这只是由未优化的代码完成的繁忙工作,以促进源代码级调试。
  • 这里是相对于 base 指针 (RBP),而不是堆栈指针 (RSP)。查看序言代码(前 3 条指令),您会看到 RBPRSP 发生了什么。如果您不了解堆栈指针是如何工作的,那么您可能会因为查看未优化的代码而感到困惑。与optimized code produced by GCC 进行比较。 @用户
猜你喜欢
  • 1970-01-01
  • 2010-10-01
  • 2021-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-25
相关资源
最近更新 更多