Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 堆栈框架的基本结构_Assembly_Stack_Frame_X86 64_Stack Frame - Fatal编程技术网

Assembly 堆栈框架的基本结构

Assembly 堆栈框架的基本结构,assembly,stack,frame,x86-64,stack-frame,Assembly,Stack,Frame,X86 64,Stack Frame,我目前正在研究堆栈帧,试图了解它是如何工作的。在阅读了几篇文章之后,这些文章总是解释说,总体结构将是: 局部变量它相当依赖于编译器。您可以尝试关闭优化或使用“extern”关键字标记函数(强制使用默认调用约定) 使用寄存器是因为这比按堆栈发送参数快得多。有几个问题。首先,这3个参数是通过寄存器传递的,因为这是ELF ABI规范的一部分。我不确定最近(x86-64)的SysV ABI文档保存在哪里(x86-64.org似乎已经不存在)。Agner Fog保存了很多优秀的文档,包括一个关于 调用\u

我目前正在研究堆栈帧,试图了解它是如何工作的。在阅读了几篇文章之后,这些文章总是解释说,总体结构将是:


局部变量它相当依赖于编译器。您可以尝试关闭优化或使用“extern”关键字标记函数(强制使用默认调用约定)


使用寄存器是因为这比按堆栈发送参数快得多。

有几个问题。首先,这3个参数是通过寄存器传递的,因为这是ELF ABI规范的一部分。我不确定最近(x86-64)的SysV ABI文档保存在哪里(x86-64.org似乎已经不存在)。Agner Fog保存了很多优秀的文档,包括一个关于

调用
\uuu stack\u check\u fail
,堆栈分配变得复杂,这是作为检测堆栈崩溃/缓冲区溢出的对策添加的。ABI的一部分还规定,在调用函数之前,堆栈必须对齐16字节。如果使用
-fno stack protector
重新编译,您将更好地了解发生了什么

此外,因为函数不做任何事情,所以它不是一个特别好的示例。它存储参数(不需要),需要12个字节
buffer1
buffer2
可能是8字节对齐的,实际上分别需要8和16字节,可能还有4个字节来对齐它们。我可能错了-我手头没有规格。这是36或40字节。然后,调用对齐需要对48个字节进行16字节对齐


我认为关闭堆栈保护并检查此叶函数的堆栈框架更具指导意义,并参考x86-64 ABI规范了解局部变量的对齐要求等。

感谢您的快速回复。在这种情况下使用寄存器是有意义的。尽管如此,我还是尝试用“gcc-O0-S-masm=intel main.c”关闭优化来组装它,但仍然得到了相同的结果。我想这只是一种方法。尽管如此,我还是想知道在本例中堆栈帧是如何组成的。有人能帮我吗?我在识别堆栈帧中的缓冲区时遇到问题…另外,缓冲区的地址是否也需要存储在堆栈的某个位置?
那里是否会有一堆未使用的空间?
需要注意的是,堆栈分配总是四舍五入到目标体系结构字大小的倍数。除此之外,ABI还可能强制执行对齐要求(例如x64上的16字节要求),这也可能会增加大小。
#include <stdio.h>

void function(int a, int b, int c);

int main()
{
        function(1, 2, 3);
        return 0;
}

void function(int a, int b, int c)
{
        char buffer1[5];
        char buffer2[10];
}
# The arguments are pushed onto the stack:
push 3
push 2
push 1
call function       # Pushes ret address onto stack and changes IP to function
...
# In function:
# Push old base pointer onto stack and set current base pointer to point to it
push rbp
mov rbp, rsp

# Reserve space for stack frame etc....
buffers   <--- SP           low address
old BP    <--- BP
ret Addr
1
2
3                           high address
    mov     edx, 3
    mov     esi, 2
    mov     edi, 1
    call    function
    .cfi_startproc
    push    rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    mov     rbp, rsp
    .cfi_def_cfa_register 6
    sub     rsp, 48
    mov     DWORD PTR [rbp-36], edi
    mov     DWORD PTR [rbp-40], esi
    mov     DWORD PTR [rbp-44], edx
    mov     rax, QWORD PTR fs:40
    mov     QWORD PTR [rbp-8], rax
    xor     eax, eax
    mov     rax, QWORD PTR [rbp-8]
    xor     rax, QWORD PTR fs:40
    je      .L3
    call    __stack_chk_fail
3            <--- SP
2
1
??
??
old BP       <--- BP
return Address
??