User:Kim Bruning/Compiler metaprogramming example
Appearance
Here is an example of how one can use a compiler to generate large amounts of assembly code. It has been linked from metaprogramming because of the length of the example.
The following programme to count from 1 to 1000 is written in C++:
/* hello.cpp */ #include <iostream> using std::cout; using std::endl; main() { for(int i=1 ; i <= 1000 ; i++) { std::cout << i << std::endl; } }
Using the GNU GCC C++ compiler g++ to generate intel x86 assembler as follows:
g++ hello.cpp -S
creates a new 221 line file hello.s as a result. The contents of this file is:
.file "hello.cpp" .local _ZSt8__ioinit .comm _ZSt8__ioinit,1,1 .text .align 2 .globl main .type main,@function main: .LFB1448: pushl %ebp .LCFI0: movl %esp, %ebp .LCFI1: subl $24, %esp .LCFI2: andl $-16, %esp movl $0, %eax subl %eax, %esp movl $1, -4(%ebp) .L2: cmpl $1000, -4(%ebp) jle .L5 jmp .L3 .L5: movl -4(%ebp), %eax movl %eax, 4(%esp) movl $_ZSt4cout, (%esp) call _ZNSolsEi movl $_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, 4(%esp) movl %eax, (%esp) call _ZNSolsEPFRSoS_E leal -4(%ebp), %eax incl (%eax) jmp .L2 .L3: movl $0, %eax leave ret .LFE1448: .Lfe1: .size main,.Lfe1-main .align 2 .type _Z41__static_initialization_and_destruction_0ii,@function _Z41__static_initialization_and_destruction_0ii: .LFB1460: pushl %ebp .LCFI3: movl %esp, %ebp .LCFI4: subl $24, %esp .LCFI5: cmpl $65535, 12(%ebp) jne .L6 cmpl $1, 8(%ebp) jne .L6 movl $_ZSt8__ioinit, (%esp) call _ZNSt8ios_base4InitC1Ev movl $__dso_handle, 8(%esp) movl $0, 4(%esp) movl $__tcf_0, (%esp) call __cxa_atexit .L6: leave ret .LFE1460: .Lfe2: .size _Z41__static_initialization_and_destruction_0ii,.Lfe2-_Z41__static_initialization_and_destruction_0ii .align 2 .type __tcf_0,@function __tcf_0: .LFB1461: pushl %ebp .LCFI6: movl %esp, %ebp .LCFI7: subl $8, %esp .LCFI8: movl $_ZSt8__ioinit, (%esp) call _ZNSt8ios_base4InitD1Ev leave ret .LFE1461: .Lfe3: .size __tcf_0,.Lfe3-__tcf_0 .align 2 .type _GLOBAL__I_main,@function _GLOBAL__I_main: .LFB1463: pushl %ebp .LCFI9: movl %esp, %ebp .LCFI10: subl $8, %esp .LCFI11: movl $65535, 4(%esp) movl $1, (%esp) call _Z41__static_initialization_and_destruction_0ii leave ret .LFE1463: .Lfe4: .size _GLOBAL__I_main,.Lfe4-_GLOBAL__I_main .section .ctors,"aw",@progbits .align 4 .long _GLOBAL__I_main .weak pthread_mutex_unlock .weak pthread_mutex_trylock .weak pthread_mutex_lock .weak pthread_create .weak pthread_setspecific .weak pthread_getspecific .weak pthread_key_delete .weak pthread_key_create .weak pthread_once .section .eh_frame,"a",@progbits .Lframe1: .long .LECIE1-.LSCIE1 .LSCIE1: .long 0x0 .byte 0x1 .string "zP" .uleb128 0x1 .sleb128 -4 .byte 0x8 .uleb128 0x5 .byte 0x0 .long __gxx_personality_v0 .byte 0xc .uleb128 0x4 .uleb128 0x4 .byte 0x88 .uleb128 0x1 .align 4 .LECIE1: .LSFDE1: .long .LEFDE1-.LASFDE1 .LASFDE1: .long .LASFDE1-.Lframe1 .long .LFB1448 .long .LFE1448-.LFB1448 .uleb128 0x0 .byte 0x4 .long .LCFI0-.LFB1448 .byte 0xe .uleb128 0x8 .byte 0x85 .uleb128 0x2 .byte 0x4 .long .LCFI1-.LCFI0 .byte 0xd .uleb128 0x5 .align 4 .LEFDE1: .LSFDE3: .long .LEFDE3-.LASFDE3 .LASFDE3: .long .LASFDE3-.Lframe1 .long .LFB1460 .long .LFE1460-.LFB1460 .uleb128 0x0 .byte 0x4 .long .LCFI3-.LFB1460 .byte 0xe .uleb128 0x8 .byte 0x85 .uleb128 0x2 .byte 0x4 .long .LCFI4-.LCFI3 .byte 0xd .uleb128 0x5 .align 4 .LEFDE3: .LSFDE5: .long .LEFDE5-.LASFDE5 .LASFDE5: .long .LASFDE5-.Lframe1 .long .LFB1461 .long .LFE1461-.LFB1461 .uleb128 0x0 .byte 0x4 .long .LCFI6-.LFB1461 .byte 0xe .uleb128 0x8 .byte 0x85 .uleb128 0x2 .byte 0x4 .long .LCFI7-.LCFI6 .byte 0xd .uleb128 0x5 .align 4 .LEFDE5: .LSFDE7: .long .LEFDE7-.LASFDE7 .LASFDE7: .long .LASFDE7-.Lframe1 .long .LFB1463 .long .LFE1463-.LFB1463 .uleb128 0x0 .byte 0x4 .long .LCFI9-.LFB1463 .byte 0xe .uleb128 0x8 .byte 0x85 .uleb128 0x2 .byte 0x4 .long .LCFI10-.LCFI9 .byte 0xd .uleb128 0x5 .align 4 .LEFDE7: .ident "GCC: (GNU) 3.2.3 20030422 (Gentoo Linux 1.4 3.2.3-r2, propolice)"