在汇编中移动堆栈指针

问题描述 投票:0回答:1

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

subq $8,%rsp

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

编辑:我的问题在这个stackoverflow回复中得到了回答。它以字节为单位,因为这是 int 的大小,它是传入的文字参数。

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

pointers assembly stack
1个回答
5
投票

你是对的。堆栈指针只是指向内存地址的指针。该内存块实际上在线程初始化时被分配为一个大块。它通常足够大以避免堆栈溢出。堆栈指针在开始时指向该块的末尾,并且每当压入新值时就会递减(每当弹出时就会递增)。将值压入堆栈只是将给定值移动到 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 的内容)。那将是一种浪费。相反,在真正需要该内存块之前,移动指针本身是一种更便宜的操作。

(如果我在这里使用的英特尔汇编语法会造成混乱,请告诉我,我只是发现它更容易编写)

© www.soinside.com 2019 - 2024. All rights reserved.