我很困惑为什么如果你想在堆栈上分配8字节存储,你使用以下命令
subq $8,%rsp
%rsp存储地址。为什么从%rsp中存储的地址中减去字面值8会分配8个字节?特别是,为什么$ x对应于x个字节?
修改:我的问题已在此stackoverflow response中得到解答。它是以字节为单位的,因为它是int的大小,这是传入的文字参数。
编辑2 :以上内容不正确。请参阅Bo的评论。
答案 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的内容)。那将是一种浪费。相反,移动指针本身是一个便宜得多的操作,直到真正需要内存块。
(请告诉我,如果我在这里使用的英特尔汇编语法会造成混淆,我发现编写起来要容易得多)