提出这个问题是因为作者正在构建编译器(src - > asm),并且正在编写用于生成汇编代码的代码。
当一个程序在基于Linux(任何操作系统真正的操作系统)的操作系统上执行时,首先发生的事情之一就是堆栈被设置并且SP寄存器被分配了堆栈开头的内存地址。 / p>
我很好奇上面这样做的责任在于程序还是操作系统本身。如果责任在于程序,那么程序如何实现(特别是在Linux基础环境中)?
个别程序在开始执行其主要功能之前必须执行哪些其他操作?
评论i386 NASM汇编代码的示例表示赞赏。此外,任何可以帮助作者实现其目标的网络资源也将非常受欢迎。
答案 0 :(得分:2)
您可以搜索有关Linux的ELF格式。 和PE-COFF for windows。
这些是可执行文件的格式,它是操作系统所知道的。 在Linux下你有负责加载程序的模块,在其他模块中使用可执行格式来正确加载程序。
编辑:来自glibc的线索给出了答案:
/*
[snip]
%esp The stack contains the arguments and environment:
0(%esp) argc
4(%esp) argv[0]
...
(4*argc)(%esp) NULL
(4*(argc+1))(%esp) envp[0]
...
NULL
[snip]
*/
[snip]
_start:
/* Clear the frame pointer. The ABI suggests this be done, to mark
the outermost frame obviously. */
xorl %ebp, %ebp
/* Extract the arguments as encoded on the stack and set up
the arguments for `main': argc, argv. envp will be determined
later in __libc_start_main. */
popl %esi /* Pop the argument count. */
movl %esp, %ecx /* argv starts just at the current stack top.*/
/* Before pushing the arguments align the stack to a 16-byte
(SSE needs 16-byte alignment) boundary to avoid penalties from
misaligned accesses. Thanks to Edward Seidl <seidl@janed.com>
for pointing this out. */
andl $0xfffffff0, %esp
pushl %eax /* Push garbage because we allocate
28 more bytes. */
/* Provide the highest stack address to the user code (for stacks
which grow downwards). */
pushl %esp
pushl %edx /* Push address of the shared library
termination function. */
[snip]
答案 1 :(得分:1)
操作系统将为您设置SP并将程序参数放在堆栈上。您的程序无需为了运行而设置任何特殊内容。
对于程序启动时Linux上的实际堆栈布局,您可以查看this document了解详细信息。
答案 2 :(得分:0)
操作系统的程序加载器负责为可执行进程分配堆栈空间。堆栈只是一个内存段(查看链接映射),加载程序在将程序加载到RAM中执行时将其修复。其他部分包括未初始化的内存和初始化的内存。加载程序也称为“可重定位”加载程序,表示它负责将程序加载到内存中方便的位置。
当对嵌入式系统进行交叉编译/链接时,链接规范包含在加载时使用的堆和堆栈信息。