Asembler linux


D.Szałkowski, Programowanie w języku asembler w systemie Linux
Programowanie w języku asembler
w systemie Linux
Dominik Szałkowski
Zakład Informatyki UMCS
dominisz@umcs.lublin.pl
http://dominisz.umcs.lublin.pl/
6 listopad 2007
1
D.Szałkowski, Programowanie w języku asembler w systemie Linux
Wstęp
Dokument zawiera podstawowe informacje na temat programowania w asemblerze w systemie
Linux.
Najnowszą wersję tego dokumentu, przykładowe programy oraz inne pomoce można znalezć na
stronie http://dominisz.umcs.lublin.pl
Uwagi na temat tego dokumentu (znalezione błędy, nieścisłości, braki) można przysyłać na adres
dominisz@umcs.lublin.pl
Tworzenie programu asemblerowego
Tworzenie programu asemblerowego podzielimy na następujące etapy:
projektowanie algorytmu,
pisanie kodu zródłowego w dowolnym edytorze tekstu  warto wykorzystać edytor dla
programistów, który oferuje podświetlanie składni np . Kate1,
kompilacja kodu zródłowego, łączenie z bibliotekami  etapy te będziemy wykonywać przy
pomocy asemblera NASM2 oraz linkera LD3. Programy te dostępne są bezpośrednio w
większości (jeśli nie we wszystkich) dystrybucji Linuksa. Po skompilowaniu otrzymujemy
plik wynikowy tzw. obiektowy. Plik obiektowy łączymy za pomocą linkera z bibliotekami i
wtedy otrzymujemy plik wykonywalny,
debugowanie programu i jego uruchamianie  wykorzystamy debuger GDB4, również
standardowo dostępny w większości dystrybucji Linuksa.
Ręczna kompilacja programu asemblerowego
Wykorzystujemy polecenia nasm i ld z odpowiednimi parametrami (opis poniżej).
nasm -f elf -g -o nazwa_programu.o nazwa_programu.asm
ld -o nazwa_programu nazwa_programu.o
Kompilacja przy pomocy programu make
Ręczne wpisywanie poleceń kompilacji i łączenia bywa niewygodne dlatego warto wykorzystać
program make5 służący do zarządzania procesem kompilacji. Tworzymy plik Makefile6 o
1 http://www.kate-editor.org/
2 http://nasm.sourceforge.net/
3 http://sourceware.org/binutils/docs-2.18/ld/index.html
4 http://sourceware.org/gdb/
5 http://www.gnu.org/software/make/
6 http://pl.wikipedia.org/wiki/Makefile
2
D.Szałkowski, Programowanie w języku asembler w systemie Linux
następującej treści:
nazwa_programu: nazwa_programu.asm
nasm -f elf -g -o nazwa_programu.o nazwa_programu.asm
ld -o nazwa_programu nazwa_programu.o
Plik Makefile jest plikiem konfiguracyjnym programu make. Zawiera reguły opisujące sposób
kompilacji programu (lub kilku programów). W pierwszej linii, przed dwukropkiem, znajduje się
nazwa reguły. Po dwukropku wypisane są nazwy plików (lub innych reguł), od których
uzależniona jest kompilacja. Kolejne linie zawierają polecenia, które mają być wykonane. Uwaga:
przed poleceniami (druga i trzecia linia) musi koniecznie pojawić się znak tabulacji (nie są to
spacje). Po utworzeniu pliku Makefile możemy uruchomić program make podając mu nazwę
reguły do wykonania.
make nazwa_programu
Możemy uruchomić program make bez podawania nazwy reguły i wtedy wykonana zostanie
pierwsza reguła opisana w pliku.
Błędy podczas kompilacji
Podczas kompilacji programów mogą pojawić się błędy. Należy wtedy przeczytać opis błędu,
zobaczyć, w której linii się pojawił a następnie poprawić go w edytorze tekstu.
nazwa_programu.asm:37: error: invalid combination of opcode and operands
Uruchomienie programu
Poprawnie skompilowany program możemy uruchomić.
./nazwa_programu
Opcje asemblera NASM
nasm -f elf -g -o nazwa_programu.o nazwa_programu.asm
-f elf  format pliku obiektowego, system Linux korzysta z formatu Executable and
Linkable Format7
-g  dołącz informacje przydatne przy debugowaniu programu
7 http://pl.wikipedia.org/wiki/Executable_and_Linkable_Format
3
D.Szałkowski, Programowanie w języku asembler w systemie Linux
-o nazwa_programu.o  nazwa wynikowego pliku obiektowego (taka nazwa jest domyślna
więc opcji tej nie trzeba dołączać)
nazwa_program.asm  nazwa pliku z kodem zródłowym
Opis wszystkich opcji asemblera NASM znajduje się w dokumentacji8.
Opcje linkera LD
ld -o nazwa_programu nazwa_programu.o
-o nazwa_programu  nazwa wynikowego pliku wykonywalnego, domyślną nazwą
tworzonego programu jest a.out ale lepiej ją zmienić na własną
nazwa_programu.o  nazwa pliku obiektowego, który chcemy łączyć z bibliotekami,
program wykonywalny może składać się z kilku plików obiektowych i w takiej sytuacji
podajemy wszystkie nazwy
Opis wszystkich opcji linkera znajduje się w dokumentacji9.
Polecenia programu GDB
Uruchamiamy program gdb z parametrem określającym nazwę programu debugowanego.
gdb ./nazwa_program
Przydatnymi poleceniami programu są
help  wyświetlenie pomocy do programu
quit  wyjście z programu
run  uruchomienie programu debugowanego
continue  wznowienie działania debugowanego programu po zatrzymaniu, program
wykonuje się do kolejnej pułapki lub do końca
list  wyświetlenie kodu zródłowego debugowanego programu, po lewej stronie
wyświetlane są numery linii, które możemy wykorzystywać w innych poleceniach
next n  wykonanie kolejnych n instrukcji, wywołanie procedury jest traktowane jako
jedna instrukcja (nie zagłebia się do procedur)
8 http://nasm.sourceforge.net/doc/nasmdoc0.html
9 http://sourceware.org/binutils/docs-2.18/ld/Options.html
4
D.Szałkowski, Programowanie w języku asembler w systemie Linux
step n  wykonanie kolejnych n instrukcji, wchodzi do procedur
nexti  wykonanie kolejnej instrukcji, uwagi jak wyżej
stepi  wykonanie kolejnej instrukcji, uwagi jak wyżej
info registers  wyświetlenie informacji o rejestrach
backtrace, info frame, info locals, info args  wyświetlenie informacji o stosie i
procedurach, wykorzystujemy gdy w programie wywoływane są procedury
break n  ustawienie pułapki w linii numer n
info breakpoints  wyświetlenie informacji o pułapkach
disable n, enable n  wyłączenie pułapki numer n oraz jej włączenie
print zmienna  wyświetlenie wartości zmiennej, dużo sposobów wyświetlania, szczegóły
po wpisaniu polecenia help print
x &zmienna  wyświetlenie zawartości pamięci od podanego adresu, dużo sposobów
wyświetlania, szczegóły po wpisaniu polecenia help x, ma większe możliwości niż
polecenie print
Do większości poleceń możemy odwoływać się za pomocą skrótów. Działa uzupełnianie nazw
poleceń i zmiennych klawiszem Tab. Naciśnięcie klawisza Enter powoduje ponowne wykonanie
ostatniego polecenia.
Przykładowa sesja GDB
Działanie debugera dbg prześledzimy na przykładowym programie, którego kod zródłowy podano
poniżej.
;; przykładowy program linuksowy do oglądania debuggerem
;; kodowanie: utf-8
;; segment danych
segment .data
;; tutaj deklarujemy zmienne
zm1 dd 0x01020304
zm2 dd 0x0f0f0f0f
zm3 dd 0
zm4 dd 0
sl1 dw 1234
5
D.Szałkowski, Programowanie w języku asembler w systemie Linux
sl2 dw 9999
nap1 db 'To jest przykladowy napis'
nap2 db 'Napis zakonczony zerem', 0
tab1 dw 10, -20, 30, -40, 50, -60
;; segment danych niezainicjalizowanych
segment .bss
sl3 resw 1
tab2 resw 6
;; segment kodu
segment .text
global _start ; zmienna musi być znana linkerowi
;; program rozpoczyna działanie od tej etykiety
_start:
nop
;;tutaj wpisujemy instrukcje programu
mov eax, [zm1]
mov ebx, [zm2]
mov [zm3], eax
mov [zm4], ebx
mov ax, [sl1]
add ax, [sl2]
mov [sl3], ax
mov ecx, 6
mov esi, tab1
mov edi, tab2
petla:
mov ax, [esi]
add ax, ax
mov [edi], ax
add esi, 2
add edi, 2
loop petla
;; wychodzimy z programu
mov eax, 1 ; numer funkcji systemowej (sys_exit)
mov ebx, 0 ; kod wyjścia
int 0x80 ; wywołanie funkcji
Kompilujemy program i uruchamiamy debuger.
6
D.Szałkowski, Programowanie w języku asembler w systemie Linux
nasm -f elf -g -o prezentacja_linux.o prezentacja_linux.asm
ld -o prezentacja_linux prezentacja_linux.o
gdb ./prezentacja_linux
Wyświetlamy okolice pierwszej instrukcji programu.
(gdb) list 30
25 global _start ; zmienna musi być znana linkerowi
26
27 ;; program rozpoczyna działanie od tej etykiety
28 _start:
29 nop
30 ;;tutaj wpisujemy instrukcje programu
31 mov eax, [zm1]
32 mov ebx, [zm2]
33 mov [zm3], eax
34 mov [zm4], ebx
Ustawiamy pułapkę na początku programu.
(gdb) break 31
Breakpoint 1 at 0x8048081: file prezentacja_linux.asm, line 31.
Uwaga: debuger gdb ma czasem kłopoty z zatrzymaniem programu na pułapce ustawionej w
pierwszej instrukcji programu. Dlatego w kodzie zródłowym tego programu jako pierwszą
umieściliśmy instrukcję nop (ang. no operation, nic nie rób) a pułapkę ustawiliśmy po niej.
Oglądamy końcowe instrukcje programu.
(gdb) list 52
47 add esi, 2
48 add edi, 2
49 loop petla
50
51 ;; wychodzimy z programu
52 mov eax, 1 ; numer funkcji systemowej (sys_exit)
53 mov ebx, 0 ; kod wyjścia
54 int 0x80 ; wywołanie funkcji
Ustawiamy pułapkę na końcu programu.
(gdb) break 52
Breakpoint 2 at 0x80480d0: file prezentacja_linux.asm, line 52.
7
D.Szałkowski, Programowanie w języku asembler w systemie Linux
Uruchamiamy program, program zatrzyma się na pierwszej pułapce.
(gdb) run
Starting program: /home/dominisz/dokumenty/asembler/prezentacja_linux
Breakpoint 1, _start () at prezentacja_linux.asm:31
31 mov eax, [zm1]
Oglądamy zawartość poszczególnych zmiennych. Najpierw wyświetlamy zmienne czterobajtowe w
systemie szesnastkowym. Polecenie wymaga adresu zmiennej i dlatego jej nazwa jest poprzedzona
znakiem & (ampersand).
(gdb) x /xw &zm1
0x80490dc : 0x01020304
(gdb) x /xw &zm2
0x80490e0 : 0x0f0f0f0f
(gdb) x /xw &zm3
0x80490e4 : 0x00000000
(gdb) x /xw &zm4
0x80490e8 : 0x00000000
Kolejne zmienne wyświetlamy jako dwubajtowe w systemie dziesiętnym (bez znaku).
(gdb) x /dh &sl1
0x80490ec : 1234
(gdb) x /dh &sl2
0x80490ee : 9999
(gdb) x /dh &sl3
0x804912c : 0
Uwaga: program gdb używa innej terminologi w odniesieniu do rozmiaru zmiennych. Zmienna
dwubajtowa nazywana jest półsłowem (ang. halfword) natomiast czterobajtowa słowem (ang.
word).
Teraz wyświetlamy napisy. Zauważmy, że napis powinien być zakończony bajtem o wartości 0.
(gdb) x /s &nap1
0x80490f0 : "To jest przykladowy napisNapis zakonczony zerem"
Wyświetlamy tablice czyli sześć zmiennych dwubajtowych wyświetlanych dziesiętnie w
reprezentacji ze znakiem.
(gdb) x /6dh &tab1
8
D.Szałkowski, Programowanie w języku asembler w systemie Linux
0x8049120 : 10 -20 30 -40 50 -60
(gdb) x /6dh &tab2
0x804912e : 0 0 0 0 0 0
Kontynuujemy działanie programu.
(gdb) continue
Continuing.
Breakpoint 2, petla () at prezentacja_linux.asm:52
52 mov eax, 1 ; numer funkcji systemowej (sys_exit)
Oglądamy wartości zmiennych zmodyfikowanych w trakcie działania programu.
(gdb) x /xw &zm3
$8 = 0x1020304
(gdb) x /xw &zm4
$9 = 0xf0f0f0f
(gdb) x /dh &sl3
0x804912c : 11233
(gdb) x /6dh &tab2
0x804912e : 20 -40 60 -80 100 -120
Kontynuujemy wykonanie programu.
(gdb) continue
Continuing.
Program exited normally.
Uwaga: wartości zmiennych musimy oglądać przed zakończeniem działania programu. Z tego
powodu ustawialiśmy pułapkę na końcu programu. Jeżeli program zakończy swoje działanie to
zmienne przyjmą wartości początkowe.
9


Wyszukiwarka

Podobne podstrony:
Linux asm lab 07 (Wprowadzenie do Linux a i Asemblera )
Linux 2000 DVB T Experiments
linux kobiety
compilar linux
Linux IPCHAINS HOWTO Appendix Differences between ipchains and ipfwadm
systemy operacyjne cw linux apache mysql
Linux materialy
Linux System Plików
Nauka słówek i memoryzacja na Puppy Linux
rs232 linux win32 cz2
linux 1 00
linux zen
linux nt loader pl 7
Asembler w TSR KURS2
03 Linux Konfiguracja serwera FTP PROFTPD
linux o3 2oo4 polish magazine ebook [snake]
02 Linux Prawa dostępu do plików i katalogów
linux nt loader pl 2

więcej podobnych podstron