为什么 C 中的这个堆栈变量不在寄存器中?

问题描述

我对如何执行缓冲区溢出攻击以及寄存器分配在编译器中的工作原理有合理的了解。

令我困惑的是,为什么 C 程序中的堆栈中有这么多东西。 考虑这个易受攻击的程序:

#include <stdio.h>

int main() {
    int a = 0;
    char str[] = "ABC";
    gets(str);
    printf("int: %d,str: %s\n",a,str);
    return a;
}

让我们运行它

> gcc run.c
> ./a.out asdfasdf
int: 1717859169,str: asdfasdf

好的,所以 str 被覆盖为 int a。但是为什么 int a 甚至在堆栈中? 做类似 (x86 asm) 之类的事情不是最简单的吗

.global _main
.text
_main:
        // omitting the gets() stuff
        movq $0,%rax
        retq

现在我们的内存流量减少了,因为堆栈上没有任何东西,代码也少得多。

tl;dr 为什么 int a 在堆栈中?

解决方法

根据我帖子的评论。 发生这种情况是因为我在编译时没有进行优化,而当我使用优化进行编译时 gcc -O3 run.c 我不会看到相同的行为。

这是一些优化的程序集

> gcc -o run -O3 run.c
> objdump -d run

...
// Set eax = 0
100003f5c: 31 c0                        xorl    %eax,%eax  
100003f5e: 48 83 c4 08                  addq    $8,%rsp
100003f62: 5b                           popq    %rbx
100003f63: 5d                           popq    %rbp
// Return 0
100003f64: c3                           retq                

还有更复杂的未优化:

...
// put 0 on the stack
100003f33: c7 45 f8 00 00 00 00         movl    $0,-8(%rbp) the stack
...
// take it off the stack and into ecx
100003f61: 8b 4d f8                     movl    -8(%rbp),%ecx 
100003f64: 89 45 e4                     movl    %eax,-28(%rbp)
100003f67: 89 c8                        movl    %ecx,%eax
100003f69: 48 83 c4 20                  addq    $32,%rsp
100003f6d: 5d                           popq    %rbp
// return 0
100003f6e: c3                           retq   

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...