ALLOCA实施 [英] Alloca implementation

查看:129
本文介绍了ALLOCA实施的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

怎样才能实现如D,C和C ++语言中使用内联x86汇编的alloca()?我想创建它的一个稍作修改的版本,但首先我需要知道标准版是如何实现的。读从编译器拆装没有帮助,因为他们的表现如此多的优化,我只是想规范形式。

How does one implement alloca() using inline x86 assembler in languages like D, C, and C++? I want to create a slightly modified version of it, but first I need to know how the standard version is implemented. Reading the disassembly from compilers doesn't help because they perform so many optimizations, and I just want the canonical form.

编辑:我想最困难的部分是,我想这有正常的函数调用语法,即使用一个裸体的功能什么的,使它看起来像正常的alloca()

I guess the hard part is that I want this to have normal function call syntax, i.e. using a naked function or something, make it look like the normal alloca().

编辑#2:啊,究竟发生了什么,你可以假设,我们不是省略帧指针

Edit # 2: Ah, what the heck, you can assume that we're not omitting the frame pointer.

推荐答案

实施的alloca 实际上要求编译器支持。这里有几个人说这是那么容易,因为:

implementing alloca actually requires compiler assistance. A few people here are saying it's as easy as:

sub esp, <size>

这是可惜只有一半的图片。是的,这将分配堆栈上的空间,但也有很多缺点。

which is unfortunately only half of the picture. Yes that would "allocate space on the stack" but there are a couple of gotchas.


  1. 如果编译器发出了code
    它引用其他变量
    相对于尤其而不是 EBP
    (典型的,如果你没有编译
    帧指针)。那么那些
    引用需要调整。即使帧指针,编译器做到这一点的时候。

  1. if the compiler had emitted code which references other variables relative to esp instead of ebp (typical if you compile with no frame pointer). Then those references need to be adjusted. Even with frame pointers, compilers do this sometimes.

更​​重要的是,根据定义,空间的alloca 分配必须是
释放时,函数退出。

more importantly, by definition, space allocated with alloca must be "freed" when the function exits.

大的是点#2。因为你的需要编译器发出code对称加&LT;大小&GT; 尤其在函数的每个出口处。

The big one is point #2. Because you need the compiler to emit code to symmetrically add <size> to esp at every exit point of the function.

最有可能的情况下,编译器提供了一些内部函数允许库作家寻求帮助编译器需要的。

The most likely case is the compiler offers some intrinsics which allow library writers to ask the compiler for the help needed.

编辑:

事实上,在glibc的(GNU的实现的libc)。实施的alloca 很简单:

In fact, in glibc (GNU's implementation of libc). The implementation of alloca is simply this:

#ifdef  __GNUC__
# define __alloca(size) __builtin_alloca (size)
#endif /* GCC.  */

编辑:

经过考虑之后,最低相信会被要求将是编译器为总是在usees任何函数使用帧指针的alloca ,不管优化设置。这将允许所有当地人通过 EBP 引用安全框架清理将由帧指针恢复到尤其。

after thinking about it, the minimum I believe would be required would be for the compiler to always use a frame pointer in any functions which usees alloca, regardless of optimization settings. This would allow all locals to be referenced through ebp safely and the frame cleanup would be handled by restoring the frame pointer to esp.

编辑:

所以,我做了一些尝试用这样的事情:

So i did some experimenting with things like this:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#define __alloca(p, N) \
    do { \
        __asm__ __volatile__( \
        "sub %1, %%esp \n" \
        "mov %%esp, %0  \n" \
         : "=m"(p) \
         : "i"(N) \
         : "esp"); \
    } while(0)

int func() {
    char *p;
    __alloca(p, 100);
    memset(p, 0, 100);
    strcpy(p, "hello world\n");
    printf("%s\n", p);
}

int main() {
    func();
}

不幸的无效正确。海湾合作委员会分析​​组装后输出。似乎优化的方式获得。这个问题似乎是因为编译器的优化,完全没有意识到我的内联汇编,它在一个意想不到的顺序做的事情的习惯和还是通过引用的东西ESP

which unfortunately does not work correctly. After analyzing the assembly output by gcc. It appears that optimizations get in the way. The problem seems to be that since the compiler's optimizer is entirely unaware of my inline assembly, it has a habit of doing the things in an unexpected order and still referencing things via esp.

下面是生成的ASM:

8048454: push   ebp
8048455: mov    ebp,esp
8048457: sub    esp,0x28
804845a: sub    esp,0x64                      ; <- this and the line below are our "alloc"
804845d: mov    DWORD PTR [ebp-0x4],esp
8048460: mov    eax,DWORD PTR [ebp-0x4]
8048463: mov    DWORD PTR [esp+0x8],0x64      ; <- whoops! compiler still referencing via esp
804846b: mov    DWORD PTR [esp+0x4],0x0       ; <- whoops! compiler still referencing via esp
8048473: mov    DWORD PTR [esp],eax           ; <- whoops! compiler still referencing via esp           
8048476: call   8048338 <memset@plt>
804847b: mov    eax,DWORD PTR [ebp-0x4]
804847e: mov    DWORD PTR [esp+0x8],0xd       ; <- whoops! compiler still referencing via esp
8048486: mov    DWORD PTR [esp+0x4],0x80485a8 ; <- whoops! compiler still referencing via esp
804848e: mov    DWORD PTR [esp],eax           ; <- whoops! compiler still referencing via esp
8048491: call   8048358 <memcpy@plt>
8048496: mov    eax,DWORD PTR [ebp-0x4]
8048499: mov    DWORD PTR [esp],eax           ; <- whoops! compiler still referencing via esp
804849c: call   8048368 <puts@plt>
80484a1: leave
80484a2: ret

正如你所看到的,它不是那么简单。不幸的是,我用我原来的说法站在你需要编译器的帮助。

As you can see, it isn't so simple. Unfortunately, I stand by my original assertion that you need compiler assistance.

这篇关于ALLOCA实施的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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