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