簡體   English   中英

堆棧、內存堆和匯編代碼的關系

[英]The relation of Stack, Memory Heap and assembly code

我試圖更詳細地了解 C/C++ 代碼的編譯過程及其內存管理。 假設以下代碼:

#include <iostream>

int main() {
    int a = 5;
    int *b = (int *) malloc(40);
    return 0;
}

我知道ab將在堆棧上創建, b值(它指向的內存)將在堆上。

編譯為程序集的代碼如下所示:

    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register %rbp
    subq    $16, %rsp
    movl    $40, %eax
    movl    %eax, %edi
    movl    $0, -4(%rbp)
    movl    $5, -8(%rbp)
    callq   _malloc
    xorl    %ecx, %ecx
    movq    %rax, -16(%rbp)
    movl    %ecx, %eax
    addq    $16, %rsp
    popq    %rbp
    retq

我的問題是;

a is on the stack (memory)這里是什么意思? 根據上面的程序集, a直接嵌入到指令$5, -8(%rbp) ,沒有對內存位置的引用。 如果它在內存上,那么a的地址a什么?

我知道_malloc在堆(內存)上創建 40 個字節並返回第一個內存地址,但我看不到堆棧是如何填充的,除了從內存中提取指令本身之外,這里沒有與內存的交互。

堆棧(內存)上的 a 在這里是什么意思?

這意味着由變量命名的對象存儲在稱為堆棧的內存部分,也就是調用堆棧。 調用堆棧包含函數的局部自動變量。

 movl $5, -8(%rbp)

rbp是幀指針。 它指向調用堆棧的當前幀。 該指令常量 5移動到 rbp 指向的內存中,偏移量為 -8 字節。 換句話說,這條指令初始化了棧上的變量a

如果它在內存上,那么a的地址是什么?

的地址a似乎是rbp - 8其中rbp是存儲在幀指針的地址。 在 C++ 領域,您可以使用 addressof 運算符來獲取地址。


堆棧(與內存相關)、rbp等都不是由 C++ 語言定義的。 這些詞在特定 CPU 架構的上下文中具有意義。

語言中沒有任何內容表明a將在堆棧中。 編譯器有權把它放在任何它想要的地方; 特別是,如果它不需要把它放在任何地方,它就沒有必要。

將 5 放入變量a后就不再使用它,因此一個體面的優化器會完全丟棄該行。

然而,你的具體情況,這在我看來就像a真的是在棧上。 它位於 %rbp 中幀指針的 -8 字節處。 這就是說,地址a是-8(%RBP),或“RBP寄存器的值,減去8”,這是非常接近的堆棧的頂部。

以獲得更詳細的信息。 堆棧存在於內存中。 讓我們假設堆棧在內存中向下增長(這是常規的),以便堆棧的“頂部”向更小的地址增長。 有一個“堆棧指針”指向堆棧的頂部,即添加到堆棧中的最后一個事物的地址(我在這里說的是一般性)。

要分配 N 字節的堆棧空間,只需從堆棧指針中減去 N。 生成的代碼通常在一條指令中完成此操作,因為它知道輸入函數所需的總空間。 要釋放該空間,代碼可以 (a) 添加 N,或 (b) 恢復堆棧指針的減法前值,該值已保存在某處。 選擇實際上是定義了編譯器系統想要如何管理堆棧的更精細的細節。

有可能用於堆棧管理的輔助寄存器。 一個常見的就是有一個“幀指針”,這就是 %rbp 在這里填充的作用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM