在汇编中移动堆栈指针

时间:2017-03-11 05:39:23

标签: pointers assembly stack

我很困惑为什么如果你想在堆栈上分配8字节存储,你使用以下命令

subq $8,%rsp

%rsp存储地址。为什么从%rsp中存储的地址中减去字面值8会分配8个字节?特别是,为什么$ x对应于x个字节?

修改:我的问题已在此stackoverflow response中得到解答。它是以字节为单位的,因为它是int的大小,这是传入的文字参数。

编辑2 :以上内容不正确。请参阅Bo的评论。

1 个答案:

答案 0 :(得分:4)

你是对的。堆栈指针只是指向内存地址的指针。该内存块实际上在线程初始化时被分配为一个大块。它通常足够大以避免堆栈溢出。堆栈指针在开始时指向该块的末尾,并且每当按下新值时递减(并且每当弹出时递增)。将值推送到堆栈只是将给定值移动到内存插槽SP指向并递减它。例如:

push rax 

是:

的同义词
sub rsp, 8
mov [rsp], rax

只有从SP中减去(而不是做push)实际上会在堆栈中留下一个可用于您自己目的的可用空间。那就是局部变量实际上是如何工作的。所以:

sub rsp, 16

将堆栈指针向下移动16个字节,这样就可以有16个字节的空间,您可以在自己的函数中使用它。要释放它,您需要记住相应地增加rsp或使用帧指针,如:

mov rbp, rsp
sub rsp, 16
; and here access the values using rbp-xxx instead of rsp+xxx

mov rsp, rbp

所以编译器可能已经完成了push rax而不是sub rsp, 8,但这实际上需要写入内存(因为需要存储rax的内容)。那将是一种浪费。相反,移动指针本身是一个便宜得多的操作,直到真正需要内存块。

(请告诉我,如果我在这里使用的英特尔汇编语法会造成混淆,我发现编写起来要容易得多)