为什么没有"分RSP"在这个函数序言说明为什么被保存在负RBP偏移函数的参数? [英] Why is there no "sub rsp" instruction in this function prologue and why are function parameters stored at negative rbp offsets?

查看:289
本文介绍了为什么没有"分RSP"在这个函数序言说明为什么被保存在负RBP偏移函数的参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这就是我理解的阅读一些内存分割文件:当一个函数被调用时,有保存帧指针在堆栈上一些指令(称为函数序言),堆栈指针的值复制到基指针和节省一些内存局部变量。

That's what I understood by reading some memory segmentation documents: when a function is called, there are a few instructions (called function prologue) that save the frame pointer on the stack, copy the value of the stack pointer into the base pointer and save some memory for local variables.

下面是一个使用GDB一个微不足道的code我试图调试:

Here's a trivial code I am trying to debug using GDB:

void test_function(int a, int b, int c, int d) {
    int flag;
    char buffer[10];

    flag = 31337;
    buffer[0] = 'A';
}

int main() {
    test_function(1, 2, 3, 4);
}

调试这个code的目的是了解在堆栈中会发生什么,当一个函数被调用:所以我必须检查在程序执行中的各个步骤的内存(调用该函数之前和期间的执行)。虽然我设法看到这样的返回地址,并通过检查基指针保存的帧指针的东西,我真的不明白我要去拆解code后写的。

The purpose of debugging this code was to understand what happens in the stack when a function is called: so I had to examine the memory at various step of the execution of the program (before calling the function and during its execution). Although I managed to see things like the return address and the saved frame pointer by examining the base pointer, I really can't understand what I'm going to write after the disassembled code.

拆解:

(gdb) disassemble main
Dump of assembler code for function main:
   0x0000000000400509 <+0>: push   rbp
   0x000000000040050a <+1>: mov    rbp,rsp
   0x000000000040050d <+4>: mov    ecx,0x4
   0x0000000000400512 <+9>: mov    edx,0x3
   0x0000000000400517 <+14>:    mov    esi,0x2
   0x000000000040051c <+19>:    mov    edi,0x1
   0x0000000000400521 <+24>:    call   0x4004ec <test_function>
   0x0000000000400526 <+29>:    pop    rbp
   0x0000000000400527 <+30>:    ret    
End of assembler dump.
(gdb) disassemble test_function 
Dump of assembler code for function test_function:
   0x00000000004004ec <+0>: push   rbp
   0x00000000004004ed <+1>: mov    rbp,rsp
   0x00000000004004f0 <+4>: mov    DWORD PTR [rbp-0x14],edi
   0x00000000004004f3 <+7>: mov    DWORD PTR [rbp-0x18],esi
   0x00000000004004f6 <+10>:    mov    DWORD PTR [rbp-0x1c],edx
   0x00000000004004f9 <+13>:    mov    DWORD PTR [rbp-0x20],ecx
   0x00000000004004fc <+16>:    mov    DWORD PTR [rbp-0x4],0x7a69
   0x0000000000400503 <+23>:    mov    BYTE PTR [rbp-0x10],0x41
   0x0000000000400507 <+27>:    pop    rbp
   0x0000000000400508 <+28>:    ret    
End of assembler dump.

据我所知,保存在堆栈帧指针被推RBP,复制堆栈指针进入基指针值是由MOV RBP,RSP但什么做的做的是让我困惑是缺乏一个子RSP $ n_bytes为节约一些内存局部变量的。我已经看到了很多展品(甚至在这里一些议题上的计算器)。

I understand that "saving the frame pointer on the stack" is done by " push rbp", "copying the value of the stack pointer into the base pointer" is done by "mov rbp, rsp" but what is getting me confused is the lack of a "sub rsp $n_bytes" for "saving some memory for local variables". I've seen that in a lot of exhibits (even in some topics here on stackoverflow).

我也读到参数应该具有基本指针正偏移量(它充满了堆栈指针的值之后),因为如果它们位于调用函数和堆栈向低地址它非常有意义,当基指针与堆栈指针的值编译器中加入一些正数追溯到堆栈中的更新。但我的code似乎将它们存储在负偏移,就像局部变量。我也无法理解为什么他们把这些寄存器(主)..不应该将它们在直接保存RSP抵消?

I also read that arguments should have a positive offset from the base pointer (after it's filled with the stack pointer value), since if they are located in the caller function and the stack grows toward lower addresses it makes perfect sense that when the base pointer is updated with the stack pointer value the compiler goes back in the stack by adding some positive numbers. But my code seems to store them in a negative offset, just like local variables.. I also can't understand why they are put in those registers (in the main).. shouldn't they be saved directly in the rsp "offsetted"?

也许这些差异是由于这样的事实,我使用的是64位系统,但我的研究并没有导致我任何会解释我面对的是什么。

Maybe these differences are due to the fact that I'm using a 64 bit system, but my researches didn't lead me to anything that would explain what I am facing.

推荐答案

System V的ABI为x86-64的指定红色区域下面<$ C $ 128字节C>%RSP 。这些128字节属于功能,只要它不调用任何其它功能(这是一个叶函数)。中断处理程序需要尊重的红色区域,因为它们是有效的非自愿的函数调用。结果所有的你的 test_function ,这是叶功能,适合局部变量红色区域,因此没​​有%RSP 的调整是必要的。 (另外,该功能是不可见的副作用,并会在任何合理的优化设置优化出)。

The System V ABI for x86-64 specifies a red zone of 128 bytes below %rsp. These 128 bytes belong to the function as long as it doesn't call any other function (it is a leaf function). Interrupt handlers need to respect the red zone, since they are effectively involuntary function calls.
All of the local variables of your test_function, which is a leaf function, fit into the red zone, thus no adjustment of %rsp is needed. (Also, the function has no visible side-effects and would be optimized out on any reasonable optimization setting).

这篇关于为什么没有&QUOT;分RSP&QUOT;在这个函数序言说明为什么被保存在负RBP偏移函数的参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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