Programowanie w asemblerze Wprowadzenie Zbigniew Jurkiewicz, Instytut Informatyki UW 17 stycznia 2017 Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Wprowadzenie Motto: “R7 is used by the processor as its program counter (PC). It is recommended that R7 not be used as a stack pointer.” Źródło: PDP-11 04/34/45/55 processor handbook, Digital Equipment Corporation, 1976. Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Wprowadzenie Po co siegać ˛ do jezyka ˛ wewnetrznego? ˛ Dostep ˛ do rejestrów sprz˛etowych procesora i kart I/O. Dostep ˛ do instrukcji, których nie zna kompilator. Precyzyjne sterowanie wykonaniem kodu w miejscach grożacych zakleszczeniem na poziomie sprz˛etu lub wyścigami. Atomowe operacje test-and-set. Naruszenie konwencji kompilatora pozwalajace ˛ na lepsza˛ optymalizacje˛ (przekazywanie parametrów, przydział pamieci, ˛ wywołania finalne tail-recursion). Dostep ˛ do nietypowych trybów pracy procesora, wykonywanie kodu sprz˛etowego z pamieci ˛ ROM itp. Ograniczenia sprz˛etowe na zasoby, np. programy wbudowane (embedded). Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Wprowadzenie Czym sie˛ za to płaci? Żmudny i mecz ˛ acy ˛ (zwłaszcza poczatkowo) ˛ proces kodowania Rewelacyjnie łatwo popełnić bład ˛ Błedy ˛ usuwa sie˛ bardzo cieżko ˛ Trudna konserwacja Znikoma przenaszalność (ale zob. „kompatybilność”) Dla typowych programów kod wygenerowany przez dobry kompilator bedzie ˛ zazwyczaj lepszy Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Wprowadzenie Łagodzenie bólu Pisać w asemblerze tylko te fragmenty, gdzie jest to niezbedne. ˛ Kod w asemblerze obudowywać dobrze zdefiniowanych interfejsami (procedury/funkcje). Starać sie˛ w miare˛ możności generować kod w asemblerze automatycznie: makra, reguły przepisywania, wzorce itp. Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Wprowadzenie Ogladanie ˛ generowanego kodu Użyć flagi -S w kompilatorze GCC, warto też dać -fverbose-asm. Szukać miejsc, które w oczywisty sposób można ulepszyć. Najlepiej wcześniej użyć profilera, aby nie ulepszać na próżno. Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Wprowadzenie Architektura komputera — próba definicji Abstrakcyjna struktura komputera, której znajomość jest niezbedna ˛ programiście piszacemu ˛ w jezyku ˛ maszynowym (lub zbliżonym). Uwaga: struktura taka może mieć różne implementacje sprz˛etowe, np. sterowanie układowe, sekwencjami taktujacymi ˛ lub mikroprogramowane. Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Wprowadzenie Poziomy interfejsu maszyn wirtualnych ISA: jezyk ˛ wewnetrzny ˛ (Instruction Set Architecture) ABI (z systemem operacyjnym) API (z bibliotekami) Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Wprowadzenie Podstawowe cechy architektury systemu komputerowego interesujace ˛ programiste: ˛ długość słowa, przestrzeń adresowa pamieci, ˛ sposoby adresacji, repertuar instrukcji, czas wykonania (zależy od postaci argumentów), organizacja stosu, system przerwań (liczba poziomów). Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Wprowadzenie Organizacja prostego komputera Klasyczny model von Neumanna. Składowe: procesor, pamieć, ˛ urzadzenia ˛ zewnetrzne. ˛ Magistrale (szyny), kanał DMA. Przechowywanie programów w pamieci, ˛ nieodróżnialność instrukcji i danych. Instrukcja = kod operacji + argumenty. Położenie argumentów: w rejestrach, w kodzie programu, w innym miejscu w pamieci. ˛ Sposób kodowania, pola. Komórki pamieci. ˛ Adresacja. Bit, bajt, słowo. Pojemność pamieci. ˛ Cykl pracy pamieci. ˛ Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Wprowadzenie Uproszczony schemat procesora Rejestry uniwersalne i specjalne Jednostka arytmetyczno-logiczna (ALU) Dekoder instrukcji Licznik rozkazów Przesłania miedzyrejestrowe ˛ Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Wprowadzenie Rejestry uniwersalne Na Pentium (32 bity): EAX (AX, AH|AL) EBX (BX, BH|BL) ECX (CX, CH|CL) EDX (DX, DH|DL) ESI (SI) EDI (DI) EBP (BP) Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Wprowadzenie Typowe rejestry specjalne licznik rozkazów (EIC, niedostepny), ˛ rejestr instrukcji (IR, niedostepny), ˛ słowo stanu procesora (FLAGS), wskaźnik stosu (ESP), rejestr adresowy i buforowy pamieci ˛ (niedostepne), ˛ rejestry segmentowe (CS, DS, ES, FS, GS, SS). Ponadto rejestr EBP najcz˛eściej używany jako wskaźnik ramki na stosie. Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Wprowadzenie Cykl rozkazowy Typowy cykl rozkazowy = fazy wykonania instrukcji: 1 fetch — pobranie z pamieci ˛ instrukcji wskazanej licznikiem rozkazów, 2 decode — rozpoznanie i ustawienie trybu argumentów 3 read — pobranie argumentów z pamieci ˛ 4 execute — wykonanie 5 write-back — zapisanie wyniku 6 interrupt — sprawdzenie, czy nie było przerwania. Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Wprowadzenie Magistrala (szyna) Maksymalna cz˛estotliwość pracy ograniczona wystepowaniem ˛ tzw. efektu bus skew — nierównomiernej predkości ˛ przepływu sygnału na poszczególnych liniach. Multipleksowanie adresów i danych oznacza dzielenie linii szyny. Polega to na przesyłaniu po tych samych liniach w różnych taktach cyklu szyny adresów i danych. Dodatkowe linia sterujace, ˛ np. stany oczekiwania (wait states) do wyrównywania szybkości pracy. Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Wprowadzenie Arytmetyka binarna i reprezentacja danych Liczby całkowite binarne bez znaku (naturalne). Operacje arytmetyczne dla liczb całkowitych bez znaku (nieujemnych) Przeniesienie (carry ) i pożyczka (borrow). Arytmetyka wielokrotnej precyzji. Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Wprowadzenie Reprezentacja liczb całkowitych ze znakiem Warianty: znak-moduł uzupełnieniowy do 1 (do zmniejszonej podstawy liczenia) uzupełnieniowy do 2 (do podstawy liczenia), najwyższy bit traktowany tak, jakby jego waga była ujemna. z przesunieciem ˛ Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Wprowadzenie Operacje arytmetyczne Przepełnienie (overflow). Reprezentacja w kodzie BCD, korekta przy dodawaniu. Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Wprowadzenie Reprezentacja liczb rzeczywistych Liczby zmiennopozycyjne, postać znak ∗ 2k ∗ f , gdzie znak jest 1 lub -1 k jest całkowite f jest ułamkiem Normalizacja — dodatkowy warunek 1 > f >= 1/2, pozwala jednoznacznie wyznaczyć k i f . Dla zera f = 0. Daje maksymalna˛ precyzje, ˛ ułatwia porównywanie Operacje arytmetyczne, denormalizacja. Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Wprowadzenie Optymalizacja procesora Przetwarzanie potokowe W przetwarzaniu potokowym (pipeline), dokonuje sie˛ równoległego przetwarzania różnych faz dla kolejnych instrukcji. Najwieksze ˛ przyśpieszenie osiaga ˛ sie˛ dla sekwencyjnych ciagów ˛ instrukcji, komplikacje powstaja˛ podczas zmian sterowania oraz przerwań. Wymagane jest wtedy opróżnienie struktury potokowej. Rozwiazanie ˛ z procesorów RISC: stosowanie delayed branch (znane też jako delay slot) — skok nastepuje ˛ dopiero po wykonaniu nastepnej ˛ instrukcji. Oczywiście kompilator musi generować odpowiedni kod „przestawiajac” ˛ odpowiednio instrukcje (możliwe w 90% przypadków). W architekturze 80x86 wprowadzono przesłania warunkowe. Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Wprowadzenie Architektura superskalarna Współczesne procesory (np. Pentium, PowerPC) posiadaja˛ kilka równoległych potoków wraz z niezależnymi modułami wykonawczymi. Pozwala to równocześnie wykonywać kilka instrukcji. Mówimy wtedy o architekturze superskalarnej. Ciekawe sa˛ jej konsekwencje dla optymalizacji. Okazuje sie, ˛ że cz˛esto warto (np. w Pentium) zastepować ˛ instrukcje złożone ciagami ˛ instrukcji prostych, bo moga˛ one być wykonywane równocześnie. Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Wprowadzenie Wydajność Przykład: Mamy program, którego wykonanie trwa 200 sekund, z czego 160 sekund to operacje mnożenia. Ile razy szybciej powinien działać układ mnożacy, ˛ aby wykonanie było 5 razy krótsze? Oznaczmy ten wzrost w: 160 sek. 200 sek. = + (200 − 160) sek. 5 w czyli 40 sek. = 160 sek. + 40 sek. w Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Wprowadzenie Literatura B.S. Chalk Organizacja i architektura komputerów A. Skorupski Podstawy budowy i działania komputerów A.S. Tanenbaum Structured Computer Organization Zaaawansowane: M.L. Schmitt Procesory Pentium Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Wprowadzenie