为什么没有"分RSP"在这个函数序言说明为什么被保存在负RBP偏移函数的参数? [英] Why is there no "sub rsp" instruction in this function prologue and why are function parameters stored at negative rbp offsets?
问题描述
这就是我理解的阅读一些内存分割文件:当一个函数被调用时,有保存帧指针在堆栈上一些指令(称为函数序言),堆栈指针的值复制到基指针和节省一些内存局部变量。
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屋!