为什么gcc反汇编为局部变量分配额外的空间? [英] Why gcc disassembler allocating extra space for local variable?

查看:375
本文介绍了为什么gcc反汇编为局部变量分配额外的空间?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  void GetInput()
{
char buffer [8];
获取(缓冲区);
puts(buffer);
}

当我在gdb的反汇编器中反汇编它时,它给出了下面的反汇编。

  0x08048464< + 0> ;: push%ebp 
0x08048465< + 1> ;: mov%esp,% ebp
0x08048467< + 3>:sub $ 0x10,%esp
0x0804846a< + 6> ;: mov%gs:0x14,%eax
0x08048470< + 12> ;: mov% eax,-0x4(%ebp)
0x08048473< + 15> ;: xor%eax,%eax
=> 0x08048475< + 17> ;: lea -0xc(%ebp),%eax
0x08048478< + 20> ;: mov%eax,(%esp)
0x0804847b< + 23> ;: call 0x8048360< ;获取@ PLT>
0x08048480< + 28> ;: lea -0xc(%ebp),%eax
0x08048483< + 31> ;: mov%eax,(%esp)
0x08048486< + 34> :call 0x8048380< puts @ plt>
0x0804848b< + 39>:mov -0x4(%ebp),%eax
0x0804848e< + 42> ;: xor%gs:0x14,%eax
0x08048495< + 49> :je 0x804849c< GetInput + 56>
0x08048497< + 51> ;: call 0x8048370< __ stack_chk_fail @ plt>
0x0804849c< + 56>:离开
0x0804849d< + 57>:ret

现在请看第三行, 0x08048467< + 3>:sub $ 0x10,%esp ,我只有8个字节被分配为局部变量,那么为什么编译器分配16个字节(0x10)。

其次, xor%gs:0x14,%eax
$ b

@Edit:如果是优化,有什么办法可以阻止它。



谢谢。

解决方案

有两件事情:
$ b


  1. 编译器可能为源代码中没有给出名称的中间表达式保留空间(或者相反,不能为可以完全存在于寄存器中的局部变量分配空间)。二进制中的堆栈槽列表不必与源代码中的局部变量列表匹配。
  2. 在某些平台上,编译器必须保持堆栈指针对齐。对于您的问题中的特定示例,编译器可能会努力将堆栈指针对齐到16个字节的边界。

关于另外一个问题,您应该单独询问, xor%gs:0x14,%eax 显然是堆栈保护机制,默认启用。如果您使用GCC,请使用 -fno-stack-protector 关闭它。


I have written simple function in C,

void GetInput()
{
    char buffer[8];
    gets(buffer);
    puts(buffer);
}

When I disassemble it in gdb's disassembler, it gives following disassembly.

   0x08048464 <+0>: push   %ebp
   0x08048465 <+1>: mov    %esp,%ebp
   0x08048467 <+3>: sub    $0x10,%esp
   0x0804846a <+6>: mov    %gs:0x14,%eax
   0x08048470 <+12>:    mov    %eax,-0x4(%ebp)
   0x08048473 <+15>:    xor    %eax,%eax
=> 0x08048475 <+17>:    lea    -0xc(%ebp),%eax
   0x08048478 <+20>:    mov    %eax,(%esp)
   0x0804847b <+23>:    call   0x8048360 <gets@plt>
   0x08048480 <+28>:    lea    -0xc(%ebp),%eax
   0x08048483 <+31>:    mov    %eax,(%esp)
   0x08048486 <+34>:    call   0x8048380 <puts@plt>
   0x0804848b <+39>:    mov    -0x4(%ebp),%eax
   0x0804848e <+42>:    xor    %gs:0x14,%eax
   0x08048495 <+49>:    je     0x804849c <GetInput+56>
   0x08048497 <+51>:    call   0x8048370 <__stack_chk_fail@plt>
   0x0804849c <+56>:    leave  
   0x0804849d <+57>:    ret    

Now please look at line number three, 0x08048467 <+3>: sub $0x10,%esp, I have only 8 bytes allocated as local variable, then why compiler is allocating 16 bytes(0x10).

Secondly, what is meaning of xor %gs:0x14,%eax.

@Edit: If it is optimization, is there any way to stop it.

Thanks.

解决方案

Two things:

  1. The compiler may reserve space for intermediate expressions to which you did not give names in the source code (or conversely not allocate space for local variables that can live entirely in registers). The list of stack slots in the binary does not have to match the list of local variables in the source code.
  2. On some platforms, the compiler has to keep the stack pointer aligned. For the particular example in your question, it is likely that the compiler is striving to keep the stack pointer aligned to a boundary of 16 bytes.

Regarding your other question that you should have asked separately, xor %gs:0x14,%eax is clearly part of a stack protection mechanism, enabled by default. If you are using GCC, turn it off with -fno-stack-protector.

这篇关于为什么gcc反汇编为局部变量分配额外的空间?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆