簡體   English   中英

簡單C ++程序的匯編輸出

[英]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.

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