728 x 90

Zacznijmy zabawę z Assemblerem

Zacznijmy zabawę z Assemblerem

Oprócz znajomości języków programowania wyższego poziomu (np. C, C++) warto zapoznać się z podstawami Asemblera, by lepiej zrozumieć działanie naszych programów.

Podstawowa znajomość asemblera przyda się podczas analizy zachowania programu, który z niewiadomych przyczyn nie działa poprawnie. Subtelne błędy mogą być spowodowane na przykład: niepoprawnie użytą konstrukcją języka, czy błędem w kompilatorze — choć to drugie rzadko się zdarza.

Ta seria postów o Asemblerze nie będzie kompletnym poradnikiem. Należy je traktować jako przegląd podstawowych zagadnień.

GENEROWANIE KODU ASEMBLERA

Według mnie bardzo dobrą metodą nauki jest analiza kodu wygenerowanego przez kompilator w procesie translacji kodu źródłowego napisanego w języku C do Asemblera. Można w tym celu skorzystać z kompilatora (np. GCC) zainstalowanego na własnym systemie.

int square(int num) {
return num * num;
}

GCC, do którego będę się odnosił, umożliwia wygenerowanie kodu Asemblera powyższego przykładu za pomocą polecenia:

gcc -O0 -S example_square.c

Po jego wykonaniu otrzymamy plik example_square.s o następującej zawartości:

 .file "example_square.c"
 .text
 .globl square
 .type square, @function
square:
.LFB0:
 .cfi_startproc
 pushq %rbp
 .cfi_def_cfa_offset 16
 .cfi_offset 6, -16
movq %rsp, %rbp
 .cfi_def_cfa_register 6
 movl %edi, -4(%rbp)
 movl -4(%rbp), %eax
 imull -4(%rbp), %eax
 popq %rbp
 .cfi_def_cfa 7, 8
ret
 .cfi_endproc
.LFE0:
 .size square, .-square
 .ident "GCC: (Debian 4.9.2-10) 4.9.2"
 .section .note.GNU-stack,"",@progbits

Oprócz właściwego kodu Asemblera, w powyższym pliku wynikowym znajdują się wskazówki dla kompilatora (wyrażenia zaczynające się od znaku kropki), ale nie czas na to.

 

SKŁADNIA AT&T ORAZ INTEL

GCC wspiera generowanie kodu Asemblera w składni AT&T oraz Intela. Wybór składni, w której kod chcemy otrzymać zależy tylko od naszych preferencji.

Składnia AT&T jest szeroko stosowana w środowisku związanym z systemami Uniksowymi, natomiast składnia Intela rozpowszechniona jest głównie w środowisku związanym z systemami firmy Microsoft.

Nie będę opisywał różnic między nimi, gdyż bardzo dobrze zostało to zrobione na tej stronie w rozdziale “Asembler AT&T kontra składnia Intela”. Osobiście preferuję składnię AT&T, dlatego w kolejnych postach będę właśnie ją stosował.

Kod zapisany z użyciem składni Intela również można wygenerować za pomocą GCC. Polecenie, które należy wykonać to:

gcc -O0 -S -masm=intel example_square.c

Poniżej znajduje się przykład kodu źródłowego zapisanego z użyciem składni AT&T (można ją rozpoznać po znakach %) oraz Intela.

 
square(int):
 pushq %rbp
movq %rsp, %rbp
 movl %edi, -4(%rbp)
 movl -4(%rbp), %eax
 imull -4(%rbp), %eax
 popq %rbp
ret

square(int):
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], edi
mov eax, DWORD PTR [rbp-4]
imul eax, DWORD PTR [rbp-4]
pop rbp
ret

 

Usługa internetowa

Czasami wygodnie jest skorzystać z usługi dostępnej w Internecie i “wyklikać” odpowiednie opcje, niż wpisywać polecenia w konsoli. Idelnym rozwiązaniem jest Compiler Explorer ‐ C++, który kompiluje kod języka C++ i wyświetla jego odpowiednik w Asemblerze. Powyższe dwa przykłady zostały utworzone właśnie z jego pomocą.

/images/compiler_explorer_cpp.png

 Źródło obrazów: opracowanie własne autora
1 comment

Leave a Comment

Your email address will not be published. Required fields are marked with *

Cancel reply

1 Comment

  • Piotr
    20 sierpnia 2017, 05:02

    Jeżeli nie programuje mikrokontrolerów albo aplikacji w których każda milisekunda ma znaczenie to znajomość assemblera jest mi kompletnie nie potrzebna.

    REPLY

Inne artykuły