Assembler w C++ Syntaksa AT&T oraz Intela

Podobne dokumenty
Praktycznie całe zamieszanie dotyczące konwencji wywoływania funkcji kręci się w okół wskaźnika stosu.

Programowanie hybrydowe C (C++) - assembler. MS Visual Studio Inline Assembler

Programowanie niskopoziomowe

4 Literatura. c Dr inż. Ignacy Pardyka (Inf.UJK) ASK MP.01 Rok akad. 2011/ / 24

Instrukcja do ćwiczenia P4 Analiza semantyczna i generowanie kodu Język: Ada

Wskaźnik może wskazywać na jakąś zmienną, strukturę, tablicę a nawet funkcję. Oto podstawowe operatory niezbędne do operowania wskaźnikami:

PROGRAMOWANIE NISKOPOZIOMOWE. Adresowanie pośrednie rejestrowe. Stos PN.04. c Dr inż. Ignacy Pardyka. Rok akad. 2011/2012

Informacje ogólne. Karol Trybulec p-programowanie.pl 1. 2 // cialo klasy. class osoba { string imie; string nazwisko; int wiek; int wzrost;

PROGRAMOWANIE NISKOPOZIOMOWE. Struktury w C. Przykład struktury PN.06. c Dr inż. Ignacy Pardyka. Rok akad. 2011/2012

Ćwiczenie nr 6. Programowanie mieszane

Podczas dziedziczenia obiekt klasy pochodnej może być wskazywany przez wskaźnik typu klasy bazowej.

Funkcje. Deklaracja funkcji. Definicja funkcji. Wykorzystanie funkcji w programie.

Informatyka I: Instrukcja 4.2

Czym są właściwości. Poprawne projektowanie klas

Programowanie Niskopoziomowe

Globalne / Lokalne. Wykład 15. Podstawy programowania (język C) Zmienne globalne / lokalne (1) Zmienne globalne / lokalne (2)

Deklaracja struktury w C++

PROGRAMOWANIE NISKOPOZIOMOWE

Podstawy języka skryptowego Lua

> C++ wskaźniki. Dane: Iwona Polak. Uniwersytet Śląski Instytut Informatyki 26 kwietnia 2017

Metody Realizacji Języków Programowania

IMIĘ i NAZWISKO: Pytania i (przykładowe) Odpowiedzi

Wskaźniki a tablice Wskaźniki i tablice są ze sobą w języku C++ ściśle związane. Aby się o tym przekonać wykonajmy cwiczenie.

7. Pętle for. Przykłady

Rekurencja (rekursja)

Jak napisać listę jednokierunkową?

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1

Programowanie hybrydowe łączenie C/C++ z asemblerem

Programowanie Niskopoziomowe

Język C++ zajęcia nr 2

Wstęp do programowania INP001213Wcl rok akademicki 2017/18 semestr zimowy. Wykład 6. Karol Tarnowski A-1 p.

Wykład 9: Polimorfizm i klasy wirtualne

C++ Przeładowanie operatorów i wzorce w klasach

Programowanie strukturalne i obiektowe. Funkcje

Klasa jest nowym typem danych zdefiniowanym przez użytkownika. Najprostsza klasa jest po prostu strukturą, np

Wstęp do programowania INP003203L rok akademicki 2018/19 semestr zimowy. Laboratorium 2. Karol Tarnowski A-1 p.

Obiekt klasy jest definiowany poprzez jej składniki. Składnikami są różne zmienne oraz funkcje. Składniki opisują rzeczywisty stan obiektu.

Programowanie Obiektowo Zorientowane w języku c++ Przestrzenie nazw

Laboratorium 1 - Programowanie proceduralne i obiektowe

Metody Metody, parametry, zwracanie wartości

Wstęp do programowania

Znajdywanie adresu funkcji z parametrami

znajdowały się różne instrukcje) to tak naprawdę definicja funkcji main.

4. Funkcje. Przykłady

Programowanie 2. Język C++. Wykład 9.

Programowanie w asemblerze Aspekty bezpieczeństwa

1. Wartość, jaką odczytuje się z obszaru przydzielonego obiektowi to: a) I - wartość b) definicja obiektu c) typ oboektu d) p - wartość

Laboratorium 1 Temat: Przygotowanie środowiska programistycznego. Poznanie edytora. Kompilacja i uruchomienie prostych programów przykładowych.

1 Wskaźniki. 1.1 Główne zastosowania wskaźników

Część XVII C++ Funkcje. Funkcja bezargumentowa Najprostszym przypadkiem funkcji jest jej wersja bezargumentowa. Spójrzmy na przykład.

METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

Wstęp do programowania INP003203L rok akademicki 2016/17 semestr zimowy. Laboratorium 1. Karol Tarnowski A-1 p.

CODE::BLOCKS & VALGRIND OPRACOWAŁ MICHAŁ BETHKE

JĘZYKI PROGRAMOWANIA Z PROGRAMOWANIEM OBIEKTOWYM. Wykład 6

Budowa i generowanie planszy

Metody Realizacji Języków Programowania

Wstęp do programowania

Architektura komputerów

1. Wypisywanie danych

ISO/ANSI C - funkcje. Funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje

Szablony. Szablony funkcji

Codecave jest to nieużywana pamięć uruchomionej aplikacji, do której można wstrzyknąć dowolny kod a następnie wykonać go.

Przekazywanie argumentów wskaźniki

Adam Kotynia, Łukasz Kowalczyk

Programowanie komputerowe. Zajęcia 4

Zadania: 1. Funkcja przeliczająca F na C: float FtoC(float f){ return (f 32.0) * 5.0 / 9.0; }

Wykład 5: Klasy cz. 3

PROGRAMOWANIE NISKOPOZIOMOWE. Systemy liczbowe. Pamięć PN.01. c Dr inż. Ignacy Pardyka. Rok akad. 2011/2012

Zadanie 2: Arytmetyka symboli

6. Pętle while. Przykłady

Wskaźniki i dynamiczna alokacja pamięci. Spotkanie 4. Wskaźniki. Dynamiczna alokacja pamięci. Przykłady

PROGRAMOWANIE NISKOPOZIOMOWE

Wykład. Materiały bazują częściowo na slajdach Marata Dukhana

Programowanie komputerowe. Zajęcia 3

Liczniki, rejestry lab. 08 Mikrokontrolery WSTĘP

Szablony funkcji i klas (templates)

JĘZYKI PROGRAMOWANIA Z PROGRAMOWANIEM OBIEKTOWYM. Wykład 5

Przepełnienie bufora i łańcuchy formatujace

#line #endif #ifndef #pragma

Programowanie C++ Wykład 2 - podstawy języka C++ dr inż. Jakub Możaryn. Warszawa, Instytut Automatyki i Robotyki

W2 Wprowadzenie do klas C++ Klasa najważniejsze pojęcie C++. To jest mechanizm do tworzenia obiektów. Deklaracje klasy :

Wstęp do informatyki- wykład 12 Funkcje (przekazywanie parametrów przez wartość i zmienną)

JAK DZIAŁAJĄ FUNKCJE PODZIAŁ PAMIĘCI

Jak napisać program obliczający pola powierzchni różnych figur płaskich?

public: // interfejs private: // implementacja // składowe klasy protected: // póki nie będziemy dziedziczyć, // to pole nas nie interesuje

Jak zawsze wyjdziemy od terminologii. While oznacza dopóki, podczas gdy. Pętla while jest

Tablice (jedno i wielowymiarowe), łańcuchy znaków

Podstawy Programowania

C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy WSKAŹNIKI KLASOWE

2. Zmienne i stałe. Przykłady Napisz program, który wypisze na ekran wynik dzielenia 281 i 117 w postaci liczby mieszanej (tj. 2 47/117).

Lab 9 Podstawy Programowania

C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów

Instrukcja do ćwiczeń nr 4 typy i rodzaje zmiennych w języku C dla AVR, oraz ich deklarowanie, oraz podstawowe operatory

Zajęcia nr 2 Programowanie strukturalne. dr inż. Łukasz Graczykowski mgr inż. Leszek Kosarzewski Wydział Fizyki Politechniki Warszawskiej

Wykład 8: klasy cz. 4

Ok. Rozbijmy to na czynniki pierwsze, pomijając fragmenty, które już znamy:

Cwiczenie nr 1 Pierwszy program w języku C na mikrokontroler AVR

Architektura komputerów. Asembler procesorów rodziny x86

Wykład I. Programowanie II - semestr II Kierunek Informatyka. dr inż. Janusz Słupik. Wydział Matematyki Stosowanej Politechniki Śląskiej

Transkrypt:

Ponownie dodaję artykuł zahaczający o temat assemblera. Na własnej skórze doświadczyłem dzisiaj problemów ze wstawką assemblerową w kodzie C++, dlatego postanowiłem stworzyć artykuł, w którym zbiorę w całość kilka często używanych trików. Artykuł jest skierowany dla użytkowników darmowego kompilatora GCC, ponoć w Visual Studio wiele problemów znika. Assembler w C++ Jeżeli nie jesteś tylko zwykłym klepaczem kodu, który zna na pamięć wszystkie interfejsy oferowane przez Jave, prawdopodobnie nie raz próbowałeś oszukać jakieś gry lub programy choćby dla rozrywki lub sprawdzania siebie. Po prostej edycji pamięci w końcu przychodzi czas, że nie da się ruszyć dalej bez znajomości assemblera. Assembler daje nieograniczone możliwości podczas analizowania oprogramowania a także w procesie jego wytwarzania. Osobiście często używam środowiska Code::Blocks, ponieważ w wygodny sposób koloruję składnie i jest lekkie, a nic oprócz kolorowania składni nie potrzebuję. Jego drugą największą zaletą (w połączeniu z GCC) jest fakt, że jest to zestaw całkowicie darmowy. Dość dużym problemem z jakim się spotkałem, są wstawki assemblerowe (inline assembler). Wydaję mi się, że GCC podchodzi do swoich użytkowników trochę niedbale. W tym artykule opiszę kilka często stosowanych zabiegów. Syntaksa AT&T oraz Intela Kompilator GCC domyślnie narzuca dla swoich użytkowników syntaksę AT&T, która w moim osobistym odczuciu jest koszmarna. Po dokładnej analizie widzę, że różnice nie wydają się szczególnie wielkie, jednak nauka jednej i drugiej jest dla mnie stratą czasu, tym bardziej kiedy z Assemblera korzystam odświętnie. W kompilatorze GCC można dodać odpowiednią flagę -masm=intel. Dzięki niej możemy bez (prawie) żadnych ograniczeń korzystać z syntaksy Intela. W tym celu w środowisku Code::Blocks wchodzimy w menu Project > Build Options > Other options. Po dopisaniu flagi zapisujemy zmiany. Aby dodać do kodu C++ fragment kodu assemblera, posługujemy się rozkazem Asm lub asm. Kod assemblera musi znajdować się w cudzysłowach. Istnieje też kilka sposobów na osiągnięcie nowych linii: Karol Trybulec p-programowanie.pl 1

1 1 void funkcja1() asm("mov eax, "); asm("push eax"); asm("add esp, "); void funkcja() mov eax, \n\ push eax \n\ add esp, \n\ "); Powyższe dwie funkcje są identyczne, różni je tylko sposób przejścia do nowych linii oraz formatowanie. Argumenty funkcji i zmienne lokalne Tworząc wstawkę assemblera, możemy w prosty sposób uzyskać dostęp do argumentów funkcji C++, w której to wstawka się znajduje oraz zmiennych lokalnych tej funkcji. Dostęp ten zapewnia nam rejestr EBP, który jest wskaźnikiem do segmentu danych na stosie. Dane wyciągamy arytmetycznie zwiększając lub zmniejszając wskaźnik: [EBP ] zmienna lokalna [EBP ] zmienna lokalna 1 [EBP] wskaźnik segmentu stosu [EBP+] wskazuje na EIP [EBP+] argument funkcji 1.. [EBP+1] argument funkcji.. Poniżej znajdują się dwie te same funkcje, napisane w czystym C++ oraz korzystając ze wstawki assemblera: Karol Trybulec p-programowanie.pl

1 1 1 1 1 1 1 1 0 1 0 1 int fun1(int a, int b) int suma; suma = a + b; suma = suma + 1; return suma; int fun(int a, int b) int suma; mov eax, [ebp + ] \n\ add eax, [ebp + 1] \n\ add eax, 1 \n\ mov [ebp-], eax \n\ "); return suma; cout << "C++: " << fun1(,) << endl; cout << "assembler: " << fun(,) << endl; Nie musisz zwracać wartości funkcji poprzez return. Wartość zwracana funkcji zawsze znajduje się w rejestrze EAX w każdej konwencji wywołania (stdcall, cdecl, fastcall): Karol Trybulec p-programowanie.pl

1 1 1 1 1 1 int suma(int a, int b) mov eax, [ebp + ] \n\ add eax, [ebp + 1] "); cout << "Suma liczb: " << suma(,) << endl; Argumenty funkcji można także umieszczać na stosie, jednak nie zwolni nas to z obowiązku operowania rejestrem EBP a więc nie ma to sensu. Funkcje w assemblerze Czasem może się zdarzyć, że będziesz potrzebował napisać funkcję w assemblerze. Jest to zabieg dość prosty, jednak w kompilatorze GCC należy skorzystać z dyrektywy extern C. W przeciwnym wypadku funkcja we wstawce assemblera, nie będzie widoczna dla reszty programu w C++. Tworząc funkcję w assemblerze piszemy w C++ jej sygnaturę. Nie zapominamy aby umieścić ją w klauzuli extern C. Następnie we wstawce assemblera definiujemy ją globalnie używając rozkazu.global poprzedzając etykietę funkcji znakiem podkreślenia _. Ostatnim krokiem jest napisanie definicji funkcji w assemblerze: Karol Trybulec p-programowanie.pl

1 1 1 1 1 1 1 1 0 1 extern "C" int suma(int a, int b);.global _suma \n\ _suma: \n\ push ebp \n\ mov ebp, esp \n\ mov eax, [ebp+] \n\ mov ebx, [ebp+1] \n\ add eax, ebx \n\ mov esp,ebp \n\ pop ebp \n\ ret \n"); cout << "Suma liczb: " << suma(,) << endl; Ponieważ całą funkcję napisaliśmy sami, niezbędne jest umieszczenie prologu i epilogu funkcji. Kod można nieco skrócić, zastępując prolog i epilog gotowymi funkcjami enter i leave. We wstawce także działają one bez zarzutu: 1 extern "C" int suma(int a, int b);.global _suma \n\ _suma: \n\ enter 0, \n\ mov eax, [ebp+] \n\ mov ebx, [ebp+1] \n\ add eax, ebx \n\ leave \n\ ret \n"); Nic nie stoi na przeszkodzie aby utworzyć do wstawek assemblerowych normalne wskaźniki funkcyjne: Karol Trybulec p-programowanie.pl

1 1 1 1 1 1 1 1 0 1 extern "C" int suma(int a, int b);.global _suma \n\ _suma: \n\ enter 0, \n\ mov eax, [ebp+]\n\ mov ebx, [ebp+1]\n\ add eax, ebx \n\ leave \n\ ret \n"); typedef int (*pt)(int, int); pt wskaznik = (pt)suma; cout << "Suma liczb: " << wskaznik(,) << endl; Podsumowanie Nie należy się bać korzystania z assemblera. Niesie on ze sobą wiele korzyści, ponieważ daje programiście możliwość tworzenie funkcji naked, które nie są wcale zmieniane przez kompilator. Jest także niezbędny podczas pisania wszelkiego typu trainerów czy hooków. Karol Trybulec p-programowanie.pl