Strona 1 z 1

[+] Assembler - wytłumaczenie działania kodu

: 26 lipca 2010, 01:13
autor: godlark
Zastanawia mnie kod w assemblerze:

Kod: Zaznacz cały

	.file	"22v2.cpp"
	.section	.text._Z1fv,"axG",@progbits,_Z1fv,comdat
	.weak	_Z1fv
	.type	_Z1fv, @function
_Z1fv:
.LFB0:
	.cfi_startproc
	.cfi_personality 0x3,__gxx_personality_v0
	pushq	%rbp
	.cfi_def_cfa_offset 16
	movq	%rsp, %rbp
	.cfi_offset 6, -16
	.cfi_def_cfa_register 6
	leave
	ret
	.cfi_endproc
.LFE0:
	.size	_Z1fv, .-_Z1fv
	.text
.globl main
	.type	main, @function
main:
.LFB1:
	.cfi_startproc
	.cfi_personality 0x3,__gxx_personality_v0
	pushq	%rbp
	.cfi_def_cfa_offset 16
	movq	%rsp, %rbp
	.cfi_offset 6, -16
	.cfi_def_cfa_register 6
	call	_Z1fv
	call	_Z1fv
	call	_Z1fv
	movl	$0, %eax
	leave
	ret
	.cfi_endproc
.LFE1:
	.size	main, .-main
	.ident	"GCC: (Debian 4.4.4-7) 4.4.4"
	.section	.note.GNU-stack,"",@progbits
Został on wygenerowany przez G++ z opcją -S

Kod: Zaznacz cały

inline void f() {}

int main() {
  f();
  f();
  f();
}
I mam w związku z tym małą prośbę. Czytałem, że gdy używamy funkcji inline, to wstawiany jest jej kod w miejsce wywołania i zaoszczędzamy na wywołaniu instrukcji "call" i przekazywaniu argumentów. Jednak tutaj widzę tą instrukcję, pewnie chodzi o inną rzecz.
Instrukcja

Kod: Zaznacz cały

.section	.text._Z1fv,"axG",@progbits,_Z1fv,comdat
nie występuje w kodzie ze zwykłą funkcją, więc pewnie w niej coś tkwi, ale z http://sourceware.org/binutils/docs-2.2 ... ml#Section dużo się nie dowiedziałem.

Jakby ktoś mógłby mi wytłumaczyć jaki jest tu ukryty haczyk w tym kodzie, to byłbym bardzo wdzięczny.

: 26 lipca 2010, 17:53
autor: grzesiek
Witam, przyznam się, że sam byłem zaskoczony i to mnie trochę zaintrygowało, więc gdy wróciłem do domu postanowiłem przeanalizować ten przykład. Natrafiłem na informację zawartą na tej stronie: http://www.redhat.com/docs/manuals/ente ... nline.html
Oto moje testy:

test.cpp

Kod: Zaznacz cały

// deklarcaja i wymóg gcc/g++ do rozwijania finkcji inline:
// __attribute__((always_inline))
inline void f() __attribute__((always_inline));

// definicja
inline void f() 
{
   int a,b,c;
   a = 1;
   b = 2;
   c = a + b;
}

int main () {
f();
f();
f();
}
test.asm

Kod: Zaznacz cały

    .file    "test.cpp"
    .text
.globl main
    .type    main, @function
main:
.LFB1:
    .cfi_startproc
    .cfi_personality 0x3,__gxx_personality_v0
    pushq    %rbp
    .cfi_def_cfa_offset 16
    movq    %rsp, %rbp
    .cfi_offset 6, -16
    .cfi_def_cfa_register 6
    movl    $1, -28(%rbp)
    movl    $2, -32(%rbp)
    movl    -32(%rbp), %eax
    movl    -28(%rbp), %edx
    leal    (%rdx,%rax), %eax
    movl    %eax, -36(%rbp)
    movl    $1, -16(%rbp)
    movl    $2, -20(%rbp)
    movl    -20(%rbp), %eax
    movl    -16(%rbp), %edx
    leal    (%rdx,%rax), %eax
    movl    %eax, -24(%rbp)
    movl    $1, -4(%rbp)
    movl    $2, -8(%rbp)
    movl    -8(%rbp), %eax
    movl    -4(%rbp), %edx
    leal    (%rdx,%rax), %eax
    movl    %eax, -12(%rbp)
    movl    $0, %eax
    leave
    ret
    .cfi_endproc
.LFE1:
    .size    main, .-main
    .ident    "GCC: (Debian 4.4.4-7) 4.4.4"
    .section    .note.GNU-stack,"",@progbits
Te kompilatory od GNU są troszkę inne jeżeli ktoś się wychował na Windowsie ;)

: 26 lipca 2010, 17:54
autor: AdeBe
"inline" może, ale nie musi być zastąpione treścią funkcji zamiast wywołaniem. Zależy to zarówno od kompilatora, danego kodu jak i opcji z jakimi kompilujesz program.
Poczytaj dokumentację do g++, powinieneś tam znaleźć opcje dotyczące optymalizacji np. "-finline-functions".
Generalnie spróbuj skompilować kod z ww. flagą, albo nawet z -O2 lub -O3. Tylko nie zdziw się wtedy, że nie za bardzo wiesz co się dzieje w programie - optymalizacje mieszają trochę w kodzie.

: 27 lipca 2010, 01:13
autor: godlark
Dzięki za pomoc. W moim przypadku wystarczyło już*opcja "-O1" i dostałem:

Kod: Zaznacz cały

	.file	"22v2.cpp"
	.text
	.p2align 4,,15
.globl main
	.type	main, @function
main:
.LFB1:
	.cfi_startproc
	.cfi_personality 0x3,__gxx_personality_v0
	xorl	%eax, %eax
	ret
	.cfi_endproc
.LFE1:
	.size	main, .-main
	.ident	"GCC: (Debian 4.4.4-7) 4.4.4"
	.section	.note.GNU-stack,"",@progbits
, natomiast opcja "-finline-fuctions" nie zmieniała nic. Podziała również sztuczka z "__attribute__((always_inline));"
Aby inny nie musieli szukać: http://gcc.gnu.org/onlinedocs/gcc-4.5.0 ... ze-Options.

PS W każdym kursie programowania piszę się, aby poznać swój kompilator, ale... ;)