gpt4 book ai didi

c - Alloca 实现

转载 作者:IT老高 更新时间:2023-10-28 12:46:34 31 4
gpt4 key购买 nike

如何在 D、C 和 C++ 等语言中使用内联 x86 汇编器实现 alloca()?我想创建一个稍微修改过的版本,但首先我需要知道标准版本是如何实现的。从编译器读取反汇编并没有帮助,因为它们执行了很多优化,我只想要规范形式。

编辑:我想困难的部分是我希望它具有正常的函数调用语法,即使用裸函数或其他东西,让它看起来像正常的 alloca()。

编辑#2:啊,到底是什么,你可以假设我们没有省略帧指针。

最佳答案

实现 alloca实际上需要编译器协助。这里有一些人说这很简单:

sub esp, <size>

不幸的是,这只是图片的一半。是的,这会“在堆栈上分配空间”,但有几个问题。

  1. 如果编译器发出了代码引用其他变量相对于 esp而不是 ebp(典型的,如果你编译没有帧指针)。那么那些引用文献需要调整。即使使用帧指针,编译器有时也会这样做。

  2. 更重要的是,根据定义,alloca 分配的空间一定是函数退出时“释放”。

最重要的是第 2 点。因为您需要编译器发出代码以对称添加 <size>esp在函数的每个退出点。

最可能的情况是编译器提供了一些内在函数,允许库编写者向编译器寻求所需的帮助。

编辑:

实际上,在 glibc(GNU 的 libc 实现)中。 alloca的执行就是这样:

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

编辑:

经过考虑,我认为编译器需要始终在任何使用 alloca 的函数中使用帧指针。 ,无论优化设置如何。这将允许通过ebp 引用所有本地人。通过将帧指针恢复到 esp 来安全地处理帧清理。 .

编辑:

所以我做了一些这样的实验:

#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();
}

不幸的是无法正常工作。通过 gcc 分析汇编输出后。似乎优化阻碍了。问题似乎是因为编译器的优化器完全不知道我的内联程序集,它习惯于以意想不到的顺序做事情并且仍然通过 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

如您所见,事情并非如此简单。不幸的是,我坚持我最初的主张,即您需要编译器帮助。

关于c - Alloca 实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/714692/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com