I have the following c++ code
int factorial(int n){ if(n==0){ return 1; } return n*factorial(n-1); } int main(void){ factorial(5); return 0; }
When I create an assembly file using g++ -S factorial.cpp I get the following:
.file "tail_call_opt.cpp" .text .globl _Z9factoriali .type _Z9factoriali, @function _Z9factoriali: .LFB0: .cfi_startproc .cfi_personality 0x0,__gxx_personality_v0 pushl %ebp .cfi_def_cfa_offset 8 movl %esp, %ebp .cfi_offset 5, -8 .cfi_def_cfa_register 5 subl $24, %esp cmpl $0, 8(%ebp) jne .L2 movl $1, %eax jmp .L3 .L2: movl 8(%ebp), %eax subl $1, %eax movl %eax, (%esp) call _Z9factoriali imull 8(%ebp), %eax .L3: leave ret .cfi_endproc .LFE0: .size _Z9factoriali, .-_Z9factoriali .globl main .type main, @function main: .LFB1: .cfi_startproc .cfi_personality 0x0,__gxx_personality_v0 pushl %ebp .cfi_def_cfa_offset 8 movl %esp, %ebp .cfi_offset 5, -8 .cfi_def_cfa_register 5 andl $-16, %esp subl $16, %esp movl $5, (%esp) call _Z9factoriali movl $0, %eax leave ret .cfi_endproc .LFE1: .size main, .-main .ident "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3" .section .note.GNU-stack,"",@progbits
I can follow most of this, but what is the purpose of the .cfi and the .LFE parts? Where can I learn more about the assembly produced by gcc?
The CFI directives are used for debugging. It allows the debugger to unwind a stack. For example: if procedure A calls procedure B which then calls a common procedure C.
Generating Assembly Code with gccWith the gcc compiler, you can obtain a listing of the assembly language generated by the compiler by using the -s option. For example, "gcc -c -S filename. c" will produce the assembly language code on file filename. s.
The GNU Assembler, commonly known as gas or as, is the assembler developed by the GNU Project. It is the default back-end of GCC. It is used to assemble the GNU operating system and the Linux kernel, and various other software.
cfi_def_cfa_offset directive is inserted to indicate that the CFA is now at an offset of only 8 bytes from the stack pointer. (The number "22" in the labels is just an arbitrary value. The compiler will generate unique label names based on some implementation detail, such as its internal numbering of basic blocks.)
These directives tell gas to emit Dwarf Call Frame Information tags which are apparently used to reconstruct a stack backtrace when a frame pointer is missing. In your case the frame pointer is present, so I guess it could be used to perform unwinding during exception handling. Such mechanism has less overhead than the old sjlj (setjump
/longjump
) one. See here, and also the linked Dwarf spec.
As for .Lxx
labels, .L
prefix indicates that the label is local to this file and so will not conflict with the same-name labels in other files. GCC generally uses .L for auto-generated labels. In this case most likely "FB
" means "function begin" and "FE
" means "function end".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With