int main(int argc, char** argv) { return 1; }
g++ -S test.cpp
生成test.s匯編文件
.file "null-test.cpp" .text .globl main .type main, @function main: .LFB0: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movl %edi, -4(%rbp) movq %rsi, -16(%rbp) movl $1, %eax popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc //在函數結束的時候使用與.cfi_startproc相配套使用 .LFE0: .size main, .-main .ident "GCC: (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3" .section .note.GNU-stack,"",@progbits
看到上面有一些語句如
cfi_def_cfa cfi_endproc cfi_startproc的命令,這些前面都有個關鍵字cfi 它是Call Frame infromation的意思。
查看堆棧的信息
CFA是什么意思就不太清楚了 可能是control flow analysis的意思吧?
.cfi_startproc 用在每個函數的開始,用於初始化一些內部數據結構
.cfi_endproc 在函數結束的時候使用與.cfi_startproc相配套使用
.cfi_def_cfa_offset 16
.cfi_def_cfa_offset offset .cfi_def_cfa_offset modifies a rule for computing CFA. Register remains the same, but offset is new. Note that it is the absolute offset that will be added to a defined register to compute CFA address.
.cfi_def_cfa 7, 8
.cfi_def_cfa register, offset .cfi_def_cfa defines a rule for computing CFA as: take address from register and add offset to it.
.cfi_def_cfa_register 6
.cfi_def_cfa_register register .cfi_def_cfa_register modifies a rule for computing CFA. From now on register will be used instead of the old one. Offset remains the same.
.cfi_offset 6, -16
.cfi_offset register, offset Previous value of register is saved at offset offset from CFA.
.cfi_startproc 和 .cfi_endproc 分別是 dwarf2 CFI 的初始過程和結束過程指令,它們隱藏了一些 CFI 有關的操作。ret 是從當前過程中返回的指令。這就是一個最簡單的 main 函數內部的三個步驟:CFI 初始操作 – 返回 – CFI 結束操作。由於第一個和最后一個步驟永遠伴隨着函數,我們大可將注意力集中在這兩個步驟之間的代碼,也就是 main 函數的實際內容。
eax 是一個通用的寄存器,根據 cdesl 調用約定(即 C 語言調用約定),在函數返回時,返回值必須保存在 eax 寄存器中,交給調用者處理。
rbp寄存器 是ebp寄存器64位擴展,ebp寄存器擴展基址指針寄存器(extended base pointer) 其內存放一個指針,該指針指向系統棧最上面一個棧幀的底部。BP
為基指針(Base Pointer)寄存器,用它可直接存取堆棧中的數據,它的作用是在調用函數時保存ESP使函數結束時可以正確返回;加E(enhance)代表增強型寄存器,用於32位數據處理。
EAX也是一種32位通用寄存器。 EAX寄存器稱為累加器,AX寄存器是算術運算的主要寄存器,所有的輸入、輸出只使用AL或AX人作為數據寄存器。在80386及其以上的微處理器中,EAX寄存器可以用來存儲單元的偏移地址。
將數據33221100H傳送到EAX寄存器的指令
EAX可稱為數據寄存器,你除了直接訪問外,還可分別對其高十六位和低十六位進行訪問。它們的低十六位就是把它們前邊兒的E去掉,即EAX的低十六位就是AX。而且它們的低十六位又可以分別進行八位訪問,也就是說,AX還可以再進行分解,即AX還可分為AH(高八位)AL(低八位)。
.file
, .text
, etc are assembler directives.
.LFB0
, .LFE0
are local labels, which are normally used as branch destinations within a function.