Linux asm lab 07 (Wprowadzenie do Linux'a i Asemblera )


Laboratorium AK  ATT asembler (Debian LINUX)
(Debian LINUX)  komendy
(nakładka na ),
przenoszenie z  notepad do (Win XP): zaznacz (Ctrl-A, Ctrl-C, & Shift-Ins)
ę!
Kompilacja (as), konsolidacja (ld) i uruchamianie programu
opcja uruchomienia z poziomu kompilatora C++ (etykieta startowa:  jak w C a nie )
tworzenie pliku wsadowego: asemblacja-ł czenie

Janusz Biernat, pa dziernik 2007 1
Laboratorium AK  ATT asembler (Debian LINUX)
Struktura programu w j zyku asemblera ATT (linux-asm dla x86/Pentium)
Zapis stałych i znaków specjalnych
znaki specjalne (\ = escape  nast pny znak specjalny)  konwencja UNIX / LINUX
Dyrektywy organizacyjne
Rezerwacja bufora w pami ci (w sekcji danych)
.ascii  STRNG zamienia ka dy znak ła cucha ( STRNG ) na bajt kodu ASCII

Janusz Biernat, pa dziernik 2007 2
Laboratorium AK  ATT asembler (Debian LINUX)

num [, fill] num  rozmiar w bajtach, fill  opcja: warto wypełnienia (domy lnie 0), *)
równowa na dyrektywa: num [, fill]
Zmienna i jej adres
Funkcje standardowe  syscall (linux-asm dla x86/Pentium)
Janusz Biernat, pa dziernik 2007 3
Laboratorium AK  ATT asembler (Debian LINUX)
Najwa niejsze funkcje systemu Linux
nazwa
%eax %ebx %ecx %edx Uwagi
1 exit status (int) Zako czenie programu
3 read numer pliku1) adres bufora rozmiar bufora Odczytuje plik do wskazanego bufora.
4 write numer pliku1) adres bufora rozmiar bufora Zapisuje z bufora do danego pliku.
5 open nazwa pliku2) lista opcji3) kod zezwole Otwiera plik o podanej nazwie. Zwraca
(lub 0666) numer pliku (w %eax) lub kod bł du.
6 close numer pliku1) Zamyka plik o danym numerze.
12 chdir nazwa katalogu4) Przeł cza do wskazanego katalogu.
19 lseek numer pliku1) tryb wska nika Pozycjonuje wska nik w pliku. Tryb
offsetu: 0  absolutny, 1  wzgl dny.
20 getpid Identyfikator ID bie cego procesu.
39 mkdir nazwa katalogu4) kod zezwole Tworzy katalog, zakładaj c e katalogi

nadrz dne ( cie ka) ju istniej .
40 rmdir nazwa katalogu4) Usuwa katalog.
41 dup numer pliku1) Zwraca nowy numer u ywanego pliku.
42 pipe pipe array Tworzy 2 numery pliku, wymuszaj c
odczyt do drugiego podczas zapisu do
pierwszego. %ebx jest wska nikiem
dwóch słów zawieraj cych te numery.
45 brk adres pułapki Ustanawia pułapk (system break)

(ostatni adres sekcji danych). Je li
%ebx=0, zwraca bie cy adres pułapki
1)
nadawany przez LINUX deskryptor (numer) pliku (file descriptor), 2) pierwsze litery nazwy pliku
3)
opcje dost pu  odczyt / zapis / odczyt i zapis, 4) pierwsze litery nazwy katalogu
Koncepcja pliku w systemie UNIX / LINUX  obsługa plików z poziomu asemblera
Pliki UNIX /LINUX, niezale nie od rodzaju i sposobu wytworzenia, s dost pne jako ła cuch bajtów.
Dost p do pliku rozpoczyna jego otwarcie przez podanie nazwy. Wtedy system operacyjny podaje
(tymczasowy) numer, zwany deskryptorem pliku (file descriptor), u ywany jako odsyłacz do pliku
podczas jego u ycia. Po zapisie lub odczycie plik nale y zamkn , co uniewa nia deskryptor.
1. Podaj do systemu Linux nazw pliku i dany tryb otwarcia (odczyt, zapis, odczyt i zapis, utwórz go
je li nie istnieje, itd.). Wykonuje to funkcja open (%eax = 5), która pobiera nazw pliku, kod trybu
oraz zbiór zezwole (permissions set) jako parametry. Adres pierwszego znaku nazwy pliku powinien
by w %ebx. W %ecx nale y wpisa kod trybu u ycia (0 dla plików, które b d tylko odczytywane,
03101 dla plików, które b d zapisywane (! zero wiod ce jest konieczne). Zbiór zezwole ma by
wpisany do %edx. Je li nie znasz kodów zezwole UNIX / LINUX, wpisz kod 0666 (! zero wiod ce
jest konieczne  patrz [1: rozdział 10, sekcja Truth, Falsehood, and Binary Numbers].
2. LINUX zwróci w %eax deskryptor pliku (file descriptor), który jest odsyłaczem do tego pliku.
3. Teraz mo na wykona funkcje read (%eax = 3), write (%eax = 4), wpisuj c deskryptor pliku do
%ebx, adres bufora danych do %ecx, rozmiar bufora do %edx. Funkcja (read / write) zwróci (w
%eax) liczb znaków przeczytanych z pliku, albo kod bł du (error code), który jest liczb ujemn .
4. Po zako czeniu operacji plik nale y zamkn za pomoc funkcji close (%eax = 6), której jedynym
parametrem jest deskryptor pliku (w %ebx). Deskryptor jest odt d uniewa niony.
Na stronie http://www.lxhp.in-berlin.de/lhpsyscal.html zamieszczono prawie kompletn list funkcji
systemu wraz z dodatkowymi informacjami. Wi cej informacji mo na te uzyska z manuala, pisz c:
man 2 SYSCALLNAME, co zwróci informacje o funkcjach systemowych z cz ci 2 UNIX manual. S
tam jednak e odwołania do wywoła funkcji z poziomu jezyka C.
Janusz Biernat, pa dziernik 2007 4
Laboratorium AK  ATT asembler (Debian LINUX)
Informacje o Linux-owej implementacji funkcji: Linux Kernel 2.4 Internals (section on how system
calls are implemented) na stronie http://www.faqs.org/docs/kernel_2_4/lki-2.html#ss2.11 .
Kod ASCII, który zawiera tylko znaki alfabetu łaci skiego (angielskiego), jest wypierany przez
standard Unicode. UTF-8 jest cz ciowo kompatybilny z ASCII (zgodno dla znaków angielskich,
rozszerzenia wielobajtowe dla innych. UTF-32 wymaga zawsze 4 bajtów na znak. Windows u ywa
UTF-16, który jest kodem o zmiennej długo ci (co najmniej 2 bajty na znak), nie jest wi c zgodny z
ASCII (znaki angielskie poprzedza bajt zerowy). Dobrym podr cznikiem Unicode jest: Joe Spolsky,
"The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode
and Character Sets (No Excuses!)" (http://www.joelonsoftware.com/articles/Unicode.html.)
Odwzorowanie programu, danych i stosu w pami ci [1]
Ka da sekcja jest ładowana do osobnego obszaru w pami ci (pocz tek bloku: adres 0x BFFF FFFF).
Zmienne rodowiskowe (environment variables) 0x BFFF FFFF
&
Arg 2
Arg 1
Nazwa programu (program name)
Liczba argumentów (# of arguments) %esp
Pami dost pna dla programu (Unmapped memory)

Kod i dane programu (Program Code and Data) break 0x 0804 8000
Kody instrukcji (.section .text) s ładowane pocz wszy od adresu 0x08048000, kody danych
(.section .data) bezpo rednio po nich, a nast pnie bufor dynamiczny (.section .bss). Ostatni
bajt nie mo e by wy ej ni w lokacji 0xBFFFFFFF. W tym miejscu Linux zaczyna tworzy swój stos,
który jest rozbudowywany w kierunku adresów rosn cych, a do swej kolejnej sekcji.
Pomi dzy nimi jest olbrzymi obszar wolny. Pocz tkowo na dnie stosu (the bottom of the stack),
którego adres jest najwy szy (the top address of memory) jest umieszczone tzw. słowo zerowe
(wszystkie bity s zerami). Po nim nast puje zako czona zerem (the null-terminated) nazwa programu
w kodzie ASCII, a po niej zmienne rodowiskowe programu (program s environment variables). Dalej
umieszczone s argumenty wywołania (command-line arguments), czyli parametry (warto ci) wpisane
do linii polecenia podczas wywołania programu. Na przykład, gdy uruchamiamy as, podajemy jako
argumenty: as, sourcefile.s, -o i objectfile.o. Po nich nast puj u ywane argumenty, które s
umieszczoane na pocz tku bloku stosu wskazanego przez wska nik stosu (stack pointer) %esp. Kolejne
operacje na stosie zmieniaj ten wska nik  składowanie zmniejsza %esp.
Obszar danych programu rozpoczyna si na dnie pami ci (the bottom of memory) i jest budowany
wzwy (kolejne lokacje maj coraz wy sze adresy). Stos rozpoczyna si na szczycie pami ci (the top
of memory) i jest rozbudowywany w dół (w kierunku adresów malej cych) po ka dym składowaniu
instrukcj push. Obszar pomi dzy stosem a obszarem danych jest z zasady niedost pny z poziomu
programu. Próba dost pu (u ycie adresu z tego obszaru) ko czy si sygnalizacj bł du , zwykle jako
"segmentation fault". To samo zdarzy si podczas próby zaadresowania obszaru poni ej adresu
0x08048000. Ten najni szy dost pny adres jest nazywany system break (albo [current] break).
Dost p do obszaru zakazanego, z ograniczeniami wynikaj cymi ze struktury systemu operacyjnego)
mo na uzyska za pomoc komunikatu przekazanego funkcjom j dra (kernel) systemu operacyjnego.
UWAGA: podobne, ale nie równowa ne działanie (pushl i popl s nierozdzielne wobec przerwania)
Instrukcja pushl %eax nie jest równowa na movl %eax, (%esp); subl $4, %esp, a instrukcja
popl %eax nie jest równowa na movl (%esp), %eax; addl $4, %esp.
Janusz Biernat, pa dziernik 2007 5
Laboratorium AK  ATT asembler (Debian LINUX)
U ycie debuggera gdb (linux-asm dla x86/Pentium)
Janusz Biernat, pa dziernik 2007 6
Laboratorium AK  ATT asembler (Debian LINUX)
U ycie edytora vi / vim [3]
nazwa pliku lub (mcedit  nakładka na ),  wersja rozszerzona
tryby pracy: (1) edycja tekstu (tryb edycji)
(2) przyjmowanie polece z klawiatury (tryb komend)  tryb startowy
(3) edycja własnego wiersza polece
vi [Enter] (2) [a] (doł cz) / [i] (wstaw) / [o] (wstaw powy ej) /& (1) & & (1) [Esc] (2)
(2) [Esc]  beep (2)  bez efektu, sygnał d wi kowy bł dnej sekwencji
(po kilku [Esc] zawsze przej cie do (2) i wtedy trzeba albo do (1) albo do (3)0
(2) [:] / [/] / [?] (3)  przej cie do edycji wiersza polece
(3) [Esc] [Enter] (2)  powrót do trybu wprowadzania polece
(3) :q!, [enter] = quit (zako cz i wró do systemu)
(3) :wq!, [enter] = write and quit (zapisz zmiany, zako cz i wró do systemu)
Tryb polece  manewrowanie kursorem
[l]  1 (1 znak w prawo, tak e [space]) [h]  !1 (1 znak w lewo, tak e [backspace])
[j] /  (1 linia w dół) / [k]  ę!1 (1 linia w gór )
1
[-]  !!ę!1 (pocz tek wiersza, linia w gór ) [+]  !! (pocz tek wiersza, linia w dół = !
! )
!
!
1
[0]  !! (pocz tek wiersza) [$]  (koniec wiersza)
[w]  pocz tek kolejnego słowa [b]  najbli szy pocz tek słowa
[Ctrl+f] / [Ctrl+d]  ekran / pół ekranu w dół [Ctrl+b] / [Ctrl+u]  ekran / pół ekranu w gór
#[G]  pocz tek wiersza o numerze #; 1[G]  pocz tek pliku, [G]  koniec pliku
[H]  pocz tek bie cego ekranu
[F1]  ekran pomocy; wyj cie: :q
Edycja polece
:r plik  wstaw (czytaj) plik
/wzorzec  szukaj wzorca w dół (w prawo)
?wzorzec  szukaj wzorca w gór (w lewo)
:q!  quit bezwarunkowo, bez zapisu zmian
:q  quit warunkowo, po zapisie zmian
:w plik  write, zapisz do pliku
:wq  write & quit, zapisz do aktualnego pliku i zako cz (tak e :x)
:help  wezwanie pomocy; wyj cie z help przez :q
Janusz Biernat, pa dziernik 2007 7
Laboratorium AK  ATT asembler (Debian LINUX)
Edycja tekstu
[i]  insert, wstaw przed kursorem
[a]  append, wstaw za kursorem
[I]  wstaw od pocz tku wiersza
[A]  wstaw na ko cu wiersza
[x]  usu znak na pozycji kursora (extract)
[X]  usu znak na pozycji przed kursorem
[d..]  delete, usu &
[dd]  usu cały wiersz
[d0]  usu od pocz tku wiersza do kursora
[d$]  usu od kursora do ko ca wiersza (tak e [D]
[dw]  usu słowo wskazane przez kursor
[r]  replace, nadpisz znak na pozycji kursora
[R]  Replace, nadpisz tekst od pozycji kursora
[y..]  copy, kopiuj &
[yy]  kopiuj aktualny wiersz do bufora
[y0]  kopiuj od pocz tku wiersza do kursora
[y$]  kopiuj od kursora do ko ca wiersza
[yw]  kopiuj słowo wskazane przez kursor
[c..]  change, zamie &
[cc]  zamie aktualny wiersz (tak e [ddI])
[c0]  zamie od pocz tku wiersza do kursora (tak e [d0i])
[c$]  zamie od kursora do ko ca wiersza (tak e [d$i])
[cw]  zamie słowo wskazane przez kursor (tak e [dwi])
[J]  join, poł cz wiersze (usu znak NewLine)&
[dd]  usu cały wiersz
[o] / [O]  wstaw wiersz poni ej / powy ej
[p]  paste, wstaw zawarto bufora za kursorem lub do kolejnego wiersza
[P]  Paste, wstaw zawarto bufora przed kursorem lub do poprzedniego wiersza
[u]  undo, anuluj
[ ]  odwołanie do konkretnego bufora
[n] / [N]  powtórz ostatnie wyszukiwanie w tym samym / przeciwnym kierunku
ZZ - ??? co to jest?, chyba quit
Janusz Biernat, pa dziernik 2007 8
Laboratorium AK  ATT asembler (Debian LINUX)
Przykładowe programy
Szukanie maksimum [1]
Kompilacja i konsolidacja (Now, assemble and link it with these commands):
Uruchomienie i sprawdzenie statusu (Now run it, and check it s status).
Janusz Biernat, pa dziernik 2007 9
Laboratorium AK  ATT asembler (Debian LINUX)
Funkcja silnia (ang. factorial) i liczenie kombinacji - bez rekurencji
arg = 5 # argument silni
.text
.globl _start
_start:
movl $arg, %eax
factorial:
pushl %ebp #standard function stuff - we have to
#restore %ebp to its prior state before
#returning, so we have to push it
movl %esp, %ebp #This is because we don t want to modify
#the stack pointer, so we use %ebp.
movl 8(%ebp), %eax #This moves the first argument to %eax
#4(%ebp) holds the return address, and
#8(%ebp) holds the first parameter
cmpl $1, %eax # koniec rekurencji, gdy argument=1
#If the number is 1, that is our base
#case, and we simply return (1 is
#already in %eax as the return value)
je end_factorial
decl %eax #otherwise, decrease the value
pushl %eax #push it for our call to factorial
call factorial #call factorial
movl 8(%ebp), %ebx #%eax has the return value, so we
#reload our parameter into %ebx
mull %ebx, %eax # multiply that by the result of the last
# call to factorial (in %eax)
#the answer is stored in %eax, which is good
# since that s where return values go.
end_factorial:
movl %ebp, %esp #standard function return stuff - we
popl %ebp #have to restore %ebp and %esp to where
#they were before the function started
ret #return to the function (this pops the
#return value, too)
movl %eax, %ebx # wynik jako status (w %bl)
movl $1, %eax # funkcja  exit
int $0x80
Janusz Biernat, pa dziernik 2007 10
Laboratorium AK  ATT asembler (Debian LINUX)
Funkcja rekurencyjna (silnia , ang. factorial)
arg = 5 # argument silni
.text
.globl _start
.globl factorial #zb dne, gdy funkcja nie jest eksportowana
_start:
movl $arg, %eax
pushl %eax # argument na stos
call factorial # wywołanie funkcji factorial, wynik w %eax
nxt_adr:
addl $4, %esp #  oczyszczenie stosu  zdj cie argumentu
# Scrubs the parameter that was pushed on the stack
movl %eax, %ebx # wynik jako status (w %bl)
movl $1, %eax # funkcja  exit
int $0x80
# definicja funkcji
.type factorial,@function
factorial:
pushl %ebp #standard function stuff - we have to
#restore %ebp to its prior state before
#returning, so we have to push it
movl %esp, %ebp #This is because we don t want to modify
#the stack pointer, so we use %ebp.
movl 8(%ebp), %eax #This moves the first argument to %eax
#4(%ebp) holds the return address, and
#8(%ebp) holds the first parameter
cmpl $1, %eax # koniec rekurencji, gdy argument=1
#If the number is 1, that is our base
#case, and we simply return (1 is
#already in %eax as the return value)
je end_factorial
decl %eax #otherwise, decrease the value
pushl %eax #push it for our call to factorial
call factorial #call factorial
movl 8(%ebp), %ebx #%eax has the return value, so we
#reload our parameter into %ebx
mull %ebx, %eax # multiply that by the result of the last
# call to factorial (in %eax)
#the answer is stored in %eax, which is good
# since that s where return values go.
end_factorial:
movl %ebp, %esp #standard function return stuff - we
popl %ebp #have to restore %ebp and %esp to where
#they were before the function started
ret #return to the function (this pops the
#return value, too)
Janusz Biernat, pa dziernik 2007 11
Laboratorium AK  ATT asembler (Debian LINUX)
Obliczanie kombinacji (przerobiona silnia)
.text
.globl _start
.globl factorial #zb dne, gdy funkcja nie jest eksportowana
_start:
movl $argn, %eax # argn = argument n  liczba elementów
movl $1, %ecx # liczenie od 1 do argk (liczba wybieranych)
pushl %eax # argument n na stos (malej cy do n-k+1)
pushl %ecx # argument 1 na stos (rosn cy a do k)
call combination # wywołanie funkcji combination, wynik w %eax
nxt_adr:
addl $4, %esp #  oczyszczenie stosu  zdj cie argumentu
# Scrubs the parameter that was pushed on the stack
movl %eax, %ebx # wynik jako status (w %bl)
movl $1, %eax # funkcja  exit
int $0x80
.type combination,@function # definicja funkcji
factorial:
pushl %ebp #standard function stuff - we have to
#restore %ebp to its prior state before
#returning, so we have to push it
movl %esp, %ebp #This is because we don t want to modify
#the stack pointer, so we use %ebp.
movl 8(%ebp), %eax #This moves the first argument to %eax
#4(%ebp) holds the return address, and
#8(%ebp) holds the first parameter
cmpl $argk, %ecx # koniec rekurencji, gdy argument2 =argk
#If the number is 1, that is our base
#case, and we simply return (1 is
#already in %eax as the return value)
je end_combine # je li %ecx=argk, b dzie ostatnie dzielenie
decl %eax #otherwise, decrease the value
incl %ecx # increase the value of denominator
pushl %eax #push it for our call to factorial
pushl %ecx #push it for our call to factorial
call combination
movl 8(%ebp), %ecx #%ecx has the return value,
movl 12(%ebp), %ebx #reload into %ebx since %eax has the return value
mull %ebx, %eax # multiply that by the result of the last
divl %ecx, %eax # call to factorial (in %eax)
#the answer is stored in %eax, which is good
# since that s where return values go.
end_combine:
movl %ebp, %esp #standard function return stuff - we
popl %ebp #have to restore %ebp and %esp to where
#they were before the function started
ret #return to the function and pop the return value,
Janusz Biernat, pa dziernik 2007 12
Laboratorium AK  ATT asembler (Debian LINUX)
Funkcja rekurencyjna  zagnie d anie (budowa stosu)
stos komentarz
pushl %eax # argument (eax) na stos
%eax esp:=esp-4 #
 old esp #
#
call factorial nxt_adr esp:=esp-4 # wywołanie, zło enie adresu
nxt_adr: %eax esp #
(addl $4, %esp, & )  old #
#
#
factorial: #
pushl %ebp %ebp esp':=esp-4 #
nxt_adr (=esp'+4) #
%eax (=esp'+8) #
 old #
movl %esp, %ebp ebp':=esp #
movl 8(%ebp), %eax eax:=[esp +8] # zło ony argument (eax)
# ze stosu do eax
cmpl $1, %eax #
je end_factorial # je li eax=1, koniec rekurencji
#
decl %eax # zmniejszanie eax
pushl %eax # kolejny poziom rekurencji
call factorial %ebp esp":=esp -4
pushl %ebp nx_ad (=esp +4) # zmniejszony argument na stos
%eax (=esp +8) # wywołanie, zło enie adresu
%ebp esp' #
nxt_adr esp (=esp'+4) #
%eax (=esp'+8) #
 old #
movl %esp, %ebp ebp":=esp #
movl 8(%ebp), %eax eax:=[esp +8] # zło ony argument (eax)
# ze stosu do eax
cmpl $1, %eax #
je end_factorial # je li eax=1, koniec rekurencji
#
decl %eax # zmniejszanie eax
pushl %eax %ebp esp*:=esp -4 # kolejny poziom rekurencji
call factorial nx_ad (=esp +4) #
pushl %ebp %eax (=esp +8) # (eax = 1)
%ebp esp":=esp -4 #
nx_ad (=esp +4) #
%eax (=esp +8) # (eax = 2)
%ebp esp' #
nxt_adr esp (=esp'+4) #
%eax (=esp'+8) # (eax = 3)
 old #
movl %esp, %ebp ebp:=esp* #
movl 8(%ebp), %eax eax:=[esp*+8] #
#
cmpl $1, %eax # eax=1
je end_factorial # skocz, bo eax = 1
# sekwencja powrotów
Janusz Biernat, pa dziernik 2007 13
Laboratorium AK  ATT asembler (Debian LINUX)
Funkcja rekurencyjna  powroty (zwalnianie stosu)
nx_ad: %ebp esp* # omini te
movl 8(%ebp), %ebx nx_ad # omini te
%eax # omini te
[ebp+8] ebx
mull %ebx, %eax %ebp # omini te
nx_ad #
%eax #
%ebp #
nxt_adr #
%eax # wyj cie z zagnie d enia
 old #
end_factorial: (ebp = esp*) #
movl %ebp, %esp #
%eax #
popl %ebp %ebp esp #
ret nx_ad #
%eax #
[ebp+8] ebx
%ebp #
nxt_adr #
%eax #
nx_ad:  old # kolejne argumenty ze stosu
movl 8(%ebp), %ebx # kolejny mno nik
mull %ebx, %eax # wymnó przez poprzedni iloczyn
#
end_factorial: #
movl %ebp, %esp #
popl %ebp %eax #
%ebp esp' #
ret nxt_adr #
%eax #
[ebp+8] ebx
 old #
nx_ad: #
movl 8(%ebp), %ebx # kolejny mno nik
mull %ebx, %eax # wymnó przez poprzedni iloczyn
#
end_factorial: #
movl %ebp, %esp #
popl %ebp #
%eax esp #
ret  old #
#
nxt_adr: #
(addl $4, %esp, & )  old esp # przywrócony
# stan pocz tkowy stosu
Literatura
[1] Programming from the Ground Up . (www& .)
[2] J. Biernat, Architektura komputerów, Oficyna Wyd. PWr, Wrocław, 2005 (wyd. IV)

[3] L. Madeja, wiczenia z systemu Linux, MIKOM, 1999 (rozdz. 4).
[4] D. Elsner, J. Fenlason & friends, Using as. The GNU assembler, Free Software Foundation Inc.,
1994, (www& .)
Janusz Biernat, pa dziernik 2007 14


Wyszukiwarka

Podobne podstrony:
lab 1 01 wprowadzenie do mathcada 1 3
wprowadzenie do systemu linux
Lab Wprowadzenie do jezyka C
Lab Wprowadzenie do systemu UNIX
Lab Wprowadzenie do jezyka C
Lab Wprowadzenie do systemu UNIX
WYKŁAD 1 Wprowadzenie do biotechnologii farmaceutycznej
Medycyna manualna Wprowadzenie do teorii, rozpoznawanie i leczenie
01 Wprowadzenie do programowania w jezyku C
wprowadzenie do buddyzmu z islamskiego punktu widzenia
1 wprowadzenie do statystyki statystyka opisowa
Informatyka Wprowadzenie Do Informatyki Ver 0 95
Wprowadzenie do psychologii wykł UG

więcej podobnych podstron