[英]assembly output of a simple C++ program
我試圖了解一個簡單的c ++程序的程序集輸出。 這是我的C ++程序。
void func()
{}
int main()
{
func();
}
當我將g ++與--save-temps選項一起使用以獲取上述程序的匯編代碼時,我將獲得以下匯編代碼。
.file "main.cpp"
.text
.globl _Z4funcv
.type _Z4funcv, @function
_Z4funcv:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size _Z4funcv, .-_Z4funcv
.globl main
.type main, @function
main:
.LFB1:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
call _Z4funcv
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE1:
.size main, .-main
.ident "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"
.section .note.GNU-stack,"",@progbits
據我對匯編的了解,任何匯編程序應有3個部分,分別是數據,文本和bss。 另外,文本部分應以“ global _start”開頭。 在此匯編代碼中我看不到它們中的任何一個。 有人可以幫我理解上面的匯編代碼。 如果您也可以與C ++代碼相關聯,那將是很好的。
任何幫助都將不勝感激。
好吧,這里是一行一行...
.file "main.cpp" # Debugging info (not essential)
.text # Start of text section (i.e. your code)
.globl _Z4funcv # Let the function _Z4funcv be callable
# from outside (e.g. from your main routine)
.type _Z4funcv, @function # Debugging info (possibly not essential)
_Z4funcv: # _Z4funcv is effectively the "name" of your
# function (C++ "mangles" the name; exactly
# how depends on your compiler -- Google "C++
# name mangling" for more).
.LFB0: # Debugging info (possibly not essential)
.cfi_startproc # Provides additional debug info (ditto)
pushq %rbp # Store base pointer of caller function
# (standard function prologue -- Google
# "calling convention" or "cdecl")
.cfi_def_cfa_offset 16 # Provides additional debug info (ditto)
.cfi_offset 6, -16 # Provides additional debug info (ditto)
movq %rsp, %rbp # Reset base pointer to a sensible place
# for this function to put its local
# variables (if any). Standard function
# prologue.
.cfi_def_cfa_register 6 # Debug ...
popq %rbp # Restore the caller's base pointer
# Standard function epilogue
.cfi_def_cfa 7, 8 # Debug...
ret # Return from function
.cfi_endproc # Debug...
.LFE0: # Debug...
.size _Z4funcv, .-_Z4funcv # Debug...
.globl main # Declares that the main function
# is callable from outside
.type main, @function # Debug...
main: # Your main routine (name not mangled)
.LFB1: # Debug...
.cfi_startproc # Debug...
pushq %rbp # Store caller's base pointer
# (standard prologue)
.cfi_def_cfa_offset 16 # Debug...
.cfi_offset 6, -16 # Debug...
movq %rsp, %rbp # Reset base pointer
# (standard prologue)
.cfi_def_cfa_register 6 # Debug...
call _Z4funcv # Call `func` (note name mangled)
movl $0, %eax # Put `0` in eax (eax is return value)
popq %rbp # Restore caller's base pointer
# (standard epilogue)
.cfi_def_cfa 7, 8 # Debug...
ret # Return from main function
.cfi_endproc # Debug...
.LFE1:
.size main, .-main # Debug...
.ident "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2" # fluff
.section .note.GNU-stack,"",@progbits # fluff
如果鏈接程序使用的是標准C或C ++庫(除非另行說明,否則通常會找到它)知道鏈接器會查找main
(而不是 start
)。 它將一些存根代碼(包含start
)鏈接到最終的可執行文件中。
因此,實際上,唯一重要的部分是...
.text
.globl _Z4funcv
_Z4funcv:
pushq %rbp
movq %rsp, %rbp
popq %rbp
ret
.globl main
main:
pushq %rbp
movq %rsp, %rbp
call _Z4funcv
movl $0, %eax
popq %rbp
ret
如果您想從頭開始,而又不想讓所有復雜的標准庫問題困擾,您可以執行以下操作並獲得與C ++代碼相同的結果:
.text
.globl _func
_func: # Just as above, really
push %ebp
mov %esp, %ebp
pop %ebp
ret
.globl _start
_start: # A few changes here
push %ebp
mov %esp, %ebp
call _func
movl $1, %eax # Invoke the Linux 'exit' syscall
movl $0, %ebx # With a return value of 0 (pick any char!)
int $0x80 # Actual invocation
退出syscall有點痛苦,但是很有必要。 如果您沒有它,它將嘗試繼續運行並“粘貼”您的代碼。 由於這可能是重要的代碼或數據,因此計算機應以“分段錯誤”錯誤阻止您。 進行退出呼叫可以避免所有這些情況。 如果您使用的是標准庫(在C ++示例中會自動發生),則鏈接程序會處理出口事務。
使用gcc -nostdlib -o test test.s
編譯(請注意,明確告知gcc 不要使用標准庫)。 我應該說這是針對32位系統的,並且很可能在64位系統上不起作用。 我沒有要測試的64位系統,但是也許一些有用的StackOverflower會加入64位轉換。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.