【问题标题】:Strange pointer position in the stack堆栈中奇怪的指针位置
【发布时间】:2017-04-03 17:17:17
【问题描述】:

我写了这个简单的代码:

#include <stdio.h>
void ok(){}

int main()
{
  int k=1;
  int l=1337;
  int *p;
  p=NULL;
  p=&k;
  ok();
} 

我已经反汇编了它,看看编译器做了什么。 使用 objdump 我获得:

0000000000400546 <main>:
  400546:       55                      push   rbp
  400547:       48 89 e5                mov    rbp,rsp
  40054a:       48 83 ec 20             sub    rsp,0x20
  40054e:       64 48 8b 04 25 28 00    mov    rax,QWORD PTR fs:0x28
  400555:       00 00 
  400557:       48 89 45 f8             mov    QWORD PTR [rbp-0x8],rax
  40055b:       31 c0                   xor    eax,eax
  40055d:       c7 45 e8 01 00 00 00    mov    DWORD PTR [rbp-0x18],0x1
  400564:       c7 45 ec 39 05 00 00    mov    DWORD PTR [rbp-0x14],0x539
  40056b:       48 c7 45 f0 00 00 00    mov    QWORD PTR [rbp-0x10],0x0
  400572:       00 
  400573:       48 8d 45 e8             lea    rax,[rbp-0x18]
  400577:       48 89 45 f0             mov    QWORD PTR [rbp-0x10],rax
  40057b:       b8 00 00 00 00          mov    eax,0x0
  400580:       48 8b 55 f8             mov    rdx,QWORD PTR [rbp-0x8]
  400584:       64 48 33 14 25 28 00    xor    rdx,QWORD PTR fs:0x28
  40058b:       00 00 
  40058d:       74 05                   je     400594 <main+0x4e>
  40058f:       e8 8c fe ff ff          call   400420 <__stack_chk_fail@plt>
  400594:       c9                      leave  
  400595:       c3                      ret    
  400596:       66 2e 0f 1f 84 00 00    nop    WORD PTR cs:[rax+rax*1+0x0]
  40059d:       00 00 00 

我可以理解除了mov QWORD PTR [rbp-0x10],0x0 之外的所有内容,这对应于(我认为)p=NULL;,但从mov QWORD PTR [rbp-0x8],rax 我知道我的指针在rbp-0x8 上并且看起来是正确的(指针的大小是8 字节)。

那么为什么在rbp-0x10 上调用mov QWORD PTR [rbp-0x10],0x0

我也不知道为什么会调用xor eax,eax;对齐?(如果是这样,为什么不使用nop)。 P.S 我知道这是将 eax 设置为零,但为什么呢?

【问题讨论】:

  • 您的指针“p”实际上位于[rbp-0x10] - 有关[rbp-0x8] 的用途的更多信息,请参阅stackoverflow.com/questions/14414763/…(特别是紧接在其前面的mov rax,QWORD PTR fs:0x28)。跨度>
  • 不要假设,您可以在 objdump 输出中将程序集与源代码混合在一起。使用调试信息编译:gcc -g file.c 并运行 objdump -S a.outobjdump --source a.out

标签: c linux gcc x86-64 disassembly


【解决方案1】:

从这些行

  6   int k=1;
  7   int l=1337;
  8   int *p;
  9   p=NULL;
 10   p=&k;

很明显,这些汇编指令对应于

  6   int k=1;
  40055d:       c7 45 e8 01 00 00 00    mov    DWORD PTR [rbp-0x18],0x1

  7   int l=1337;
  400564:       c7 45 ec 39 05 00 00    mov    DWORD PTR [rbp-0x14],0x539

  9   p=NULL;
  40056b:       48 c7 45 f0 00 00 00    mov    QWORD PTR [rbp-0x10],0x0
  400572:       00 

 10   p=&k;
  400573:       48 8d 45 e8             lea    rax,[rbp-0x18]
  400577:       48 89 45 f0             mov    QWORD PTR [rbp-0x10],rax

所以局部变量p被放置在[rbp-0x10]并占据一个QWORD[rbp-0x10][rbp-0x8]rbp-0x10 + 0x8 == rbp-0x8

【讨论】:

  • 但是 p(在 rbp-0x10 上)和 l(在 rbp-0x14 上)之间的空间是 0x04。指针不是 8 字节长吗?他怎么能适应0x04的空间?
  • @Ofey 地址 rbp -0x14 和 rbp - 0x10 的空间被变量 l 占用。地址 rbp-0x10 和 rbp-0x8 处的空间被指针 p 占用。 rbp-0x10 + 8 == rbp-0x8。
  • 这就是我所缺少的!谢谢!
猜你喜欢
  • 1970-01-01
  • 2015-11-16
  • 1970-01-01
  • 2013-01-20
  • 2012-02-14
  • 1970-01-01
  • 2015-08-05
  • 1970-01-01
  • 2021-03-16
相关资源
最近更新 更多