Programowanie niskopoziomowe Programowanie
niskopoziomowe w systemie operacyjnym oraz poza nim Tworzenie
programu zawierającego procedury asemblerowe
1
Programowanie niskopoziomowe w systemie operacyjnym
Programowanie w systemie operacyjnym nie wymaga od programisty dokładnej znajomości maszyny.
Środowisko pracy programu jest przygotowywane przez system operacyjny i moduł startowy.
Programista ma za zadanie jedynie utworzyć użytkową część programu. 2
Programowanie niskopoziomowe w systemie operacyjnym
Funkcje realizowane przez system operacyjny: Alokacja pamięci Obsługa systemu plików Obsługa wejścia/wyjścia Obsługa wyjątków
3
Programowanie niskopoziomowe poza systemem operacyjnym
Programy uruchamiane poza środowiskiem systemu operacyjnego operują bezpośrednio na zasobach sprzętowych maszyny.
Programista ma w tym przypadku obowiązek zaalokować pamięć, m.in. stos.
Takie programy muszą być pisane w asemblerze. 4
Programowanie niskopoziomowe poza systemem operacyjnym
Przykłady: Bootloader – program ładujący system operacyjny jądro systemu operacyjnego samodzielna aplikacja systemu wbudowanego
5
Tworzenie programu z wykorzystaniem programowania niskopoziomowego
Podczas tworzenia aplikacji możliwe jest równoległe stosowanie języków wysokopoziomowych i asemblera.
Tworzony program może się składać z wielu plików pisanych w różnych językach programowania.
Ta uniwersalność jest możliwa dzięki wieloetapowemu procesowi tłumaczenia tekstu programu na kod wykonywalny. 6
Proces tłumaczenia kodu programu pisanego w języku wysokiego poziomu
preprocessing i kompilacja Tekst programu
Zbiór obiektowy konsolidacja (linkowanie)
Kod wykonywalny
Zbiory Zbiory obiektowe Zbiory obiektowe biblioteczne obiektowe biblioteczne biblioteczne 7
Proces tłumaczenia kodu programu – wersja z asemblacją kompilacja asemblacja Tekst programu
Wygenerowany kod asemblera
Zbiór obiektowy Kod wykonywalny Zbiory Zbiory obiektowe Zbiory obiektowe biblioteczne obiektowe biblioteczne biblioteczne
konsolidacja 8
Pojawia się możliwość łączenia programowania w języku wysokiego poziomu i w asemblerze - programowanie hybrydowe kompilacja asemblacja Tekst programu
Wygenerowany kod asemblera
Kod asemblera utworzony przez programistę
Zbiór obiektowy
konsolidacja Zbiory obiektowe biblioteczne
Kod wykonywalny
Zbiór obiektowy asemblacja 9
Łączenie programowania w asemblerze i języku wysokiego poziomu jest możliwe nawet, jeśli proces kompilacji pomija postać asemblerową
Tekst programu
kompilacja
Kod asemblera utworzony przez programistę
Zbiór obiektowy
Zbiory obiektowe biblioteczne
konsolidacja
Kod wykonywalny
Zbiór obiektowy asemblacja 10
Zbiory obiektowe
Zbiory obiektowe zawierają kod wykonywalny, w którym nie zostały zdefiniowane odwołania do obiektów zewnętrznych: zmiennych i procedur definiowanych w innych modułach.
Zbiory obiektowe zawierają informację o tych odwołaniach i udostępnianych przez siebie obiektach.
11
Zbiory obiektowe
Popularne formaty zbiorów obiektowych:
ELF (Executable and Linking Format) – popularny w systemie Linux
COFF (Common Object File Format)- używany w systemie Windows
SOM (System Object Module) – format wprowadzony przez firmę Hewlet Packard
12
Wiązanie obiektów i odwołań
Dzięki zawartym informacjom konsolidator może wiązać obiekty z odwołaniami w innych modułach.
Konsolidator nie musi mieć dostępu do informacji, w jakim języku był pisany dany moduł, podlegający łączeniu.
13
Zasady łączenia kodu w języku wysokiego poziomu i w asemblerze Aby możliwe było wiązanie odwołań do obiektów z innych modułów muszą one być:
Zewnętrzne – w modułach odwołujących się do nich Publiczne – w modułach, gdzie są definiowane
14
Obiekty zewnętrzne w języku C i w asemblerze
Niezdefiniowane funkcje w języku C są z założenia traktowane przez kompilator jako zewnętrzne.
Kompilator jest informowany o istnieniu nazwy zewnętrznej zmiennej za pomocą słowa kluczowego extern.
Wszelkie obiekty zewnętrzne muszą zostać w asemblerze zadeklarowane za pomocą extern. 15
Obiekty publiczne w języku C i w asemblerze
Jedynie obiekty publiczne są dostępne dla innych modułów.
W języku C wszystkie obiekty globalne są publiczne, poza zdefiniowanymi ze słowem static.
W asemblerze obiekty publiczne definiuje się z zastosowaniem słowa static lub global. 16
Przykład łączenia kodu w języku C i w asemblerze - kod w języku C extern void f1 (void); /* słowo extern pokazuje, że jest to obiekt zewnętrzny*/ int main () { f1(); return 0; } 17
Przykład łączenia kodu w języku C i w asemblerze - kod w asemblerze .text .global f1 f1: pushl %ebp movl %esp, %ebp movl $4, %eax /* 4 to funkcja systemowa "write" */ movl $1, %ebx /* 1 to stdout */ movl $tekst, %ecx /* adres tekstu */ movl $len, %edx /* długość tekstu w bajtach */ int $0x80 /* wywołanie przerwania systemowego */ popl %ebp ret
.data tekst: .string "Hello world\n" len = . - tekst
18
Przekazywanie argumentów funkcji z języka C do asemblera
Argumenty w języku C przekazywane są do funkcji przez stos: odkładane są na stosie od ostatniego do pierwszego.
W asemblerze do odczytu argumentów posługujemy się wskaźnikiem stosu.
pushl %ebp movl %esp, %ebp
19
Zwracanie wartości funkcji do programu w języku C
W języku C wartość funkcji jest zwracana programowi wywołującemu w jednym z rejestrów mikroprocesora.
W architekturze i386 do zwracania używa się rejestru EAX, bądź jego "mniejszych" odpowiedników, tj. AX i AH/AL.
Przykład: by funkcja, napisana w asemblerze zwróciła "1" przed rozkazem ret należy napisać: movl $1, %eax 20
Łączenie kodu w języku C i w asemblerze w jednym zbiorze
Możliwe jest dołączanie do kodu w języku C ciągu instrukcji asemblera za pomocą tzw. wstawek asemblerowych, definiowanych słowem „asm”.
Przykład: int main () { asm ("nop"); } 21
Dyrektywy organizacji segmentów w asemblerze Pisząc program w asemblerze dla architektury x86 należy wskazać segmenty, w których definiowane są poszczególne obiekty za pomocą dyrektyw organizacji segmentów:
.section .text - kod programu .section .rodata – stałe inicjalizowane .section .data - zmienne inicjalizowane .section .bss - dane nieinicjalizowane
22
Przykład użycia dyrektyw organizacji segmentów w asemblerze ;initializing data .section .data x: .byte 128 y: .long 1,1000,10000 ;initializing ascii data .ascii "hello” asciz "hello„ ;allocating memory in bss .section .bss .equ BUFFSIZE 1024 .comm z, 4, 4
;one byte initialized to 128 ;3 long words
;ascii without null character ;ascii with \0
;define a constant ;allocate 4 bytes for x with ;4-byte alignment
23
Przykład użycia dyrektyw organizacji segmentów w asemblerze, cd. ;making symbols externally visible .section .data .globl w ;declare externally visible ;e.g: int w = 10 .text .globl fool ;e.g: fool(void) {…} fool: … leave return
24