正如Jester所說,問題在於,當你使用pop %rbp
/ret
時,堆棧指針指向其他地方,所以你沒有得到舊的%rbp
和返回地址。 (你永遠不會寫信給你彈出的位置,由於另一個潛在的錯誤,所以我不能確切地告訴你你的ret
到底是哪一個無效的地址。)
如果你做一個堆棧幀(mov %rsp, %rbp
),那麼使用相對於%rbp
的偏移量是正常的。有趣的事實:movq $200, -8(%rbp)
需要one byte less machine code比等效的movq $200, 8(%rsp)
。 (使用%rsp
作爲基址寄存器不幸總是需要一個SIB字節編碼的有效地址。)
使用%rbp
也意味着引用如果你推/彈出東西,任何給定的堆棧地址也不會改變的表達(在32位代碼中常見,堆棧參數爲ABI,但在64位代碼中很少見,64位gcc在32位之前切換爲-fomit-frame-pointer)。
您的movq $200, -8(%rsp)
使用您保留的16B以外的空間。這是我之前提到的「其他潛在的錯誤」。
當前%rsp
下面使用高達128B實際上是不在SysV的ABI的錯誤:異步事件(信號處理等)避免重挫的red zone,不調用任何其他功能都可以如此之小功能避免花費修改%rsp
來預留空間。 x86-64有15個通用寄存器(不包括堆棧指針),因此中小型函數通常不需要使用堆棧,而是保存/恢復調用保存的寄存器。或者用於本地陣列。
Windows ABI不使用紅色區域,因此即使您不用call
自己動手,也可能會潛在低於%rsp
的內存。
有關調用約定/ ABI的鏈接,請參閱x86標記wiki。
您需要釋放您分配的空間。通過將'rbp'移回'rsp'或通過撤消'sub'。 – Jester
@Jester,所以我可以做相反的減法並將16添加到rsp? – mosmo
是的,如果沒有使用幀指針,這是通常的方式。當你的情況確實有幀指針時,通常只是移回到'rsp'。 – Jester