Programowanie w asemblerzeAsembler i jego jezyk
Zbigniew Jurkiewicz, Instytut Informatyki UW
17 stycznia 2017
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Asembler
Asembler = program, przetwarzajacy plik zródłowy ztekstem programu w symbolicznym jezyku wewnetrznymna plik wynikowy, tzw. moduł (ang. object code).Moduł zawiera ten sam program w postaciprzetłumaczonej na jezyk maszynowy.Oprócz pliku wynikowego asembler produkuje jeszcze plikizawierajace wydruk programu oraz liste odwołan (ang.cross-references).W trakcie zajec posługiwac sie bedziemy głównieasemblerem nasm.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Asemblacja
W celu przetłumaczenia programu znajdujacego sie napliku program.asm nalezy napisacbash-2.04$ nasm -f elf program.asm
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Linkowanie
Poniewaz program moze składac sie z kilku modułów,przed załadowaniem musimy poddac go (byc moze wraz zinnymi modułami) procesowi konsolidacji (zwanemupotocznie linkowaniem).W przypadku programu znajdujacego sie w pojedynczympliku wynikowym konsolidator wywołujemy przezbash-2.04$ ld program.o
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Linkowanie
Konsolidator normalnie tworzy plik wynikowy o nazwiea.out.Chcac otrzymac plik o innej nazwie, np. program, nalezyuzyc opcji -obash-2.04$ ld -o program program.o
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Asembler
Jezyk asemblera ułatwia zapisywanie programów w jezykuwewnetrznym, dzieki wielu udogodnieniom, nienaruszajacych jednakze podstawowej zasady:
Pojedynczej instrukcji jezyka wewnetrznego odpowiadadokładnie jedna instrukcja jezyka asemblera.
Zamiast adresów mozna uzywac symbolicznychidentyfikatorów.Oprócz instrukcji jezyka wewnetrznego w programie mogawystapic dodatkowe linie — polecenia (zwane tezpseudoinstrukcjami).Sa one wykonywane w trakcie asemblacji —przekształcania takiego programu na jezyk wewnetrzny.Inaczej mówiac, steruja przebiegiem asemblacji.Wiele asemblerów oferuje dodatkowe mechanizmy, takiejak definiowanie makrooperacji i asemblacja warunkowa.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Składnia
Instrukcje zapisywane w jezyku asemblera maja nastepujacapostac:
〈etykieta〉: 〈operacja〉 〈argumenty〉 ;〈komentarz〉
na przykład
start: add eax,ebx ;To jest instrukcja
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Składnia
Wymagane jest jedynie pole operacji, pozostałe moga bycpuste.Etykieta jest symboliczna reprezentacja adresu instrukcji,uzywanego w instrukcjach sterujacych, np.
jmp start
Etykiety w programie w asemblerze powinny wystapic wpierwszej kolumnie i byc zakonczone dwukropkiem.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Składnia
Polecenia maja nieco inna postac:
〈nazwa〉 〈polecenie〉 〈argumenty〉 ;〈komentarz〉
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Stałe
W programie moga wystapic nastepujace rodzaje stałych:
binarne ciag cyfr binarnych zakonczony litera B, np.10110011B.
dziesietneszesnastkowe nalezy je poprzedzac przez 0x, np. piszemy
0xA5.znakowe ciag znaków umieszczonych w apostrofach, np.
’Ala’.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Stałe
Stałe symboliczne mozna definiowac uzywajac polecenia equ
rozmiar equ 10...add ebx,rozmiar
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Symbole
Symboliczne nazwy słuza do identyfikowania zmiennych,stałych, etykiet, segmentów itp.Z kazdym symbolem zwiazane sa dodatkowe informacjezwane atrybutami, takie jak sekcja, adres i typ.Wyrózniony symbol $ oznacza licznik asemblacji, jegowartoscia jest zawsze offset (czyli adres) biezacoasemblowanej linii programu. Jest on zerowany przyrozpoczeciu asemblacji segmentu.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Wyrazenia
W argumentach instrukcji i polecen moga wystapicwyrazenia.Asembler zastepuje je ich obliczona wartoscia, np.ponizszy kod uzywa wyrazenia do okreslenia długoscipewnego obszaru danychinfo db 1,2,3,’Jakis napis’,10dl_info equ $-info
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Rezerwacja pamieci („zmienne”)
Polecenia rezerwacji pamieci słuza do deklarowania irezerwowania komórek danych oraz ewentualnegoinicjowania ich zawartosci.Rezerwacja jednego lub kilku bajtów ma postac
〈nazwa〉 db 〈wartosc poczatkowa〉[,...]na przykładbajt db 5lista db 1,2,3,4kom db ’Komunikat’,10
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Rezerwacja pamieci („zmienne”)
Jesli nie wymagamy inicjalizacji nalezy uzywac polecenia resb
klawisz resb 1
z podana specyfikacja liczby rezerwowanych komórek (w tymprzypadku 1), co pozwala rezerwowac ciag komórek, np.
wektor resb 25
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Rezerwacja pamieci („zmienne”)
Jesli chcemy zarezerwowac obszar danych i wypełnic gopowtarzajacymi sie wartosciami, nalezy skorzystac z prefiksutimes, z argumentem podajacym liczbe powtórzen
liczby: times 17 db 31okresowe: times 30 db 1,2,3,4
(w ostatnim przypadku kolejne komórki inicjowane bedawartosciami 1, 2, 3, 4, 1, 2, 3, 4, 1,...).
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Rezerwacja pamieci („zmienne”)
Polecenie dw rezerwuje słowo pamieci (dwa bajty), zaspolecenie dd podwójne słowo (cztery bajty). Przypominamy, zezapis
oper dw 0x4315
równowazny jest (na procesorach Intela)
oper db 0x15,0x43
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Rezerwacja pamieci („zmienne”)
Niestety asembler NASM nie zapamietuje rozmiarówzwiazanych z symbolami („typów”), dlatego czasem trzebaprefiksowac argument adresowy podajac rozmiar, np.
mov word [oper],1
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Sekcje
Program napisany w asemblerze składa sie z sekcji.Kazda sekcja rozpoczyna sie poleceniem section, np.aby zadeklarowac sekcje z instrukcjami („kodem”)programu piszemy
section .text...
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Sekcje
Standardowe nazwy sekcji to
.text — zawiera instrukcje wykonywalne,
.data — zawiera dane inicjowane oraz
.bss — zawiera dane nie inicjowane.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Sekcje
Oczywiscie mozna definiowac własne sekcje o innychnazwach.Dodatkowymi atrybutami okresla sie wtedy przeznaczeniesekcji.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Eksportowanie
Procedury wywoływane tylko lokalnie w modulerównowazne sa etykietom w kodzie i nie musza bycdeklarowane.Procedury przeznaczone do wywoływania z innychmodułów nalezy eksportowac – deklarowac jako globalne.Moduł (byc moze jedyny) zawierajacy program głównypowinien eksportowac symbol _start.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Eksportowanie
Symbole eksportowane z modułu (np. nazwy procedur)deklaruje sie poleceniem
global 〈symbol〉,...
natomiast symbole importowane z innych modułów poleceniem
extern 〈symbol〉,...
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Struktura programu
Program w jezyku asemblera powinien miec wiec nastepujacastrukture:
;; Definicje stałych...
;; Sekcja danychsection .data...
;; Sekcja kodusection .textglobal _start ;Program główny;-)
_start: ......mov eax,1int 0x80
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Struktura programu
;; Procedury (w tym samym segmencie)...
;; Globalne nie inicjowane dane roboczesection .bss...
;; Koniec programu
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Proste programy
Pierwszy program bedzie obliczac silnie liczby 4.Wynik zostanie zwrócony na zewnatrz jako argumentwywołania systemowego exit.Wywołania systemowe słuza do komunikacji z systememoperacyjnym.W Linuksie sa realizowane przerwaniem programowym0x80 lub instrukcja syscall.W rejestrze eax umieszcza sie numer wywołania, a wpozostałych argumenty.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Proste programy
section .textglobal _start ;Declaracja dla linkera (ld)
;; Wywołania systemowe
SYS_EXIT equ 1
;; Argument
ARG equ 4
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Proste programy
_start: ;Poczatek programu (punkt wejscia)mov ebx,1 ;Obliczana wartoscmov ecx,ARG
l1: cmp ecx,1 ;Czy juz koniec?jle koniecimul ebx,ecxdec ecx ;Zmniejszamy argumentjmp l1
koniec: mov eax,SYS_EXIT ;numer wywołania systemowegoint 0x80 ;wywołanie systemowe
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Proste programy
Przed uruchomieniem program musimy zasemblowac izlinkowac.
$ nasm -f elf pierwszy.asm$ ld -o pierwszy pierwszy.o$ ./pierwszy$ echo $?24
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Proste programy — wypisywanie
Najprostszy program wyswietlajacy na ekranie konsoli „Witaj,swiecie!” mógłby wygladac tak:
section .textglobal _start ;Declaracja dla linkera (ld)
STDOUT equ 1 ;Standardowe wyjscie (deskryptor)
;; Wywołania systemowe
SYS_EXIT equ 1SYS_WRITE equ 4
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Proste programy — wypisywanie
_start: ;Poczatek programu (punkt wejscia)mov edx,dlug ;długosc bufora (arg 3)mov ecx,napis ;adres bufora (arg 2)mov ebx,STDOUT ;deskryptor pliku (arg 1)mov eax,SYS_WRITE ;numer wywołania systemowegoint 0x80 ;wywołanie systemowe
mov ebx,0 ;poprawny powrót (arg 1)mov eax,SYS_EXIT ;numer wywołania systemowegoint 0x80 ;wywołanie systemowe
section .data
;; Komunikat do wypisania
napis db ’Witaj swiecie!’,0xa ;napis zakonczony znakiem LFdlug equ $-msg ;długosc napisu
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Proste programy — wypisywanie
Sekcja .data w zasadzie była zbedna, komunikat dowypisania mozna było umiescic w sekcji .text, poniewaznie jest on modyfikowany.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Procedury
Procedury wywołuje sie instrukcjacall 〈nazwa〉
Zakonczenie procedury i powrót do miejsca wywołanianastepuje jedynie po wykonaniu instrukcji
ret
Nie ma domyslnego zakonczenia po napotkaniu koncatekstu procedury, jak w niektórych jezykachprogramowania.Adres powrotny jest przekazywany (automatycznie) nawierzchołku stosu.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Parametry
Dopóki korzystamy jedynie z własnych procedur pisanychw asemblerze, sposób przekazywania parametrów izwracania wyników jest nasza sprawa.Inaczej bedzie, gdy program nasz ma wywoływacprocedury biblioteczne (np. wywołania systemowe Unixa)lub komunikowac sie z procedurami pisanymi w jezyku C.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Parametry
Istnieja dwa typowe sposoby przekazywania parametrów.Pierwszy z nich to umieszczenie wszystkich parametrówna stosie.
Z tej metody korzysta sie dla wywołan systemowych wsystemach BSD.
Drugi sposób to przekazanie parametrów w ustalonychrejestrach.
W ten sposób przekazuje sie w systemie Linux parametrydla wywołan systemowych.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Parametry
Oczywiscie mozliwe sa równiez techniki posrednie, np.kilka pierwszych parametrów w rejestrach, a reszta nastosie.Jest to konieczne, gdy liczba parametrów jest wieksza nizliczba dostepnych rejestrów (nb. dla wywołansystemowych nie ma tego problemu).Zwracana wartosc równiez moze znajdowac sie wrejestrze lub ustalonym miejscu na stosie.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Parametry
Poniewaz korzystamy z systemu Linux, argumenty dlawywołan systemowych przekazywac powinnismy wkolejnych rejestrach (ebx, ecx, edx dla trybu32-bitowego), natomiast wynik znajdziemy w rejestrze eax.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Prosty program z procedura
Zmodyfikujemy nasz program na liczenie silni tak, aby wydzielicjej obliczanie w osobna procedure.
section .textglobal _start ;Declaracja dla linkera (ld)
;; Wywołania systemowe
SYS_EXIT equ 1
;; Argument
ARG equ 4
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Prosty program z procedura
_start: ;Poczatek programu (punkt wejscia)push dword ARGcall silnia ;Wynik bedzie w eaxmov ebx,eaxmov eax,SYS_EXIT ;numer wywołania systemowegoint 0x80 ;wywołanie systemowe
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Prosty program z procedura
silnia:push ebpmov ebp,esppush ebxmov ebx,[ebp+8] ;Argument (pierwszy i jedyny)mov eax,1 ;Obliczana wartosc
l1: cmp ebx,1 ;Czy juz koniec?jle koniecimul eax,ebxdec ebx ;Zmniejszamy argumentjmp l1
koniec: pop ebxpop ebpret
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Zachowywanie rejestrów
Pamietajmy o zachowywaniu i odtwarzaniu rejestrów,których zawartosc jest niszczone przez wywoływanaprocedure.Moze to byc dokonywane w miejscu wywołania procedury(strategia caller saves) lub w samej procedurze (calleesaves).
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Zachowywanie rejestrów
Powszechnie uzywana jest ta druga strategia. Istnieja potemu dwa powody.Po pierwsze, w przypadku zmian w kodzie procedurypowodujacych uzycie nowego rejestru nalezy odnalezc isprawdzic wszystkie wywołania tej procedury.Po drugie, jesli zachowanie rejestrów znajduje sie wprocedurze, to realizujace je ciagi instrukcji push i popwystapia tylko raz, a wiec kod bedzie krótszy.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Prosty program z proceduraTe sama procedure mozna zapisac rekurencyjnie.
section .textglobal _start ;Declaracja dla linkera (ld)
;; Wywołania systemowe
SYS_EXIT equ 1
;; Argument
ARG equ 4
_start: ;Poczatek programu (punkt wejscia)push dword ARGcall silnia ;Wynik bedzie w eaxmov ebx,eaxmov eax,SYS_EXIT ;numer wywołania systemowegoint 0x80 ;wywołanie systemowe
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Prosty program z procedura
silnia:push ebpmov ebp,espmov eax,[ebp+8] ;Argument (pierwszy i jedyny)cmp eax,1 ;Czy juz koniec?jle koniecdec eax ;Zmniejszamy argumentpush eaxcall silnia ;Wynik bedzie w eaxadd esp,4 ;Czyscimy stosimul eax,[ebp+8]
koniec: pop ebpret
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Procedury biblioteczneSpróbujmy w programie „powitalnym” zamiast wywołaniasystemowego wywołac biblioteczna procedure printf.
section .textglobal _start ;Declaracja dla linkera (ld)extern printf,exit
_start: ;Poczatek programu (punkt wejscia)push napiscall printf
push dword 0call exit
section .data
;; Komunikat do wypisania
napis db ’Witaj swiecie!’,0xa,0 ;napis zakonczony znakiem LF i zerem
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Procedury biblioteczne
Zmieni sie sposób linkowania programu
$ nasm -f elf szosty.asm$ ld -o szosty szosty.o -lc -dynamic-linker /lib/ld-linux.so.2$ ./szostyWitaj swiecie!
Opcja -l podaje nazwe zadanej biblioteki (z pominieciemprzedrostka lib, natomiast opcja -dynamic-linkerumozliwia dynamiczne wiazanie bibliotek.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Procedury z argumentami bezposrednio w kodzie
Argumenty dla procedur mozna równiez umieszczacbezposrednio w sekcji kodu, choc rzadko korzysta sie z tejmozliwosci. Przykład takiego wywołania:...call drukujdb ’Witaj swiecie’,0 ;Napis zakonczony zerem!...
Procedura drukuj otrzyma wtedy na wierzchołku stosutylko adres swojego argumentu — napisu.Uzyje go do wydrukowania napisu, po czym zamieni nastosie na otrzymany „przy okazji” drukowania adrespowrotny (miejsce w kodzie bezposrednio zaargumentami).
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Procedury z argumentami bezposrednio w kodzie
drukuj: pop eaxl1: cmp byte [eax], 0
je l2push eaxmov edx,1mov ecx,eaxmov ebx,1mov eax,SYS_WRITEint 0x80pop eaxinc eaxjmp l1
l2: inc eaxpush eaxret
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Komunikacja z programami w jezyku C
Czesto procedury pisane w asemblerze stanowia fragmentprogramu pisanego w jezyku programowania wyzszegopoziomu, np. C, Lispie lub Pascalu.Procedura taka powinna wtedy uwzgledniac konwencjestosowane przez uzywany kompilator.Dla kompilatora gcc argumenty sa przekazywane nastosie podzielonym na ramki (rekordy aktywacji) procedur.Biezaca ramke wskazuje rejestr ebp.Aby miec wygodny dostep do parametrów, nalezy tenrejestr zachowac i przestawic na wierzchołek swojej ramki.Nazywamy to prologiem procedury.Podobnie przed zakonczeniem procedury nalezyodtworzyc stara zawartosc rejestru ramki.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Komunikacja z programami w jezyku C
W sumie szkielet prostej procedury ma nastepujaca postac
proc: push ebpmov ebp,espmov eax,[ebp+8] ;pierwszy argument...mov eax,〈wynik〉pop ebpret
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Komunikacja z programami w jezyku C
Istnieja dwie specjalne instrukcje enter i leave do uzywaniazamiast prologu i epilogu. W najprostszym przypadkupowyzsza procedure mozna równiez zapisac nastepujaco
proc: enter 0,0mov eax,[ebp+8] ;pierwszy argument...mov eax,〈wynik〉leaveret
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Komunikacja z programami w jezyku C
Ponadto procedury w asemblerze powinny zachowaczawartosc rejestrów ebx, esi, edi (sa one uzywane dlazmiennych deklarowanych jako register) oraz cs, ds, esi ss.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Komunikacja z programami w jezyku C
Popatrzmy na (nieco „zakrecony”) program powitalny wkombinacji asemblera i C. Najpierw czesc w asemblerze
section .datahello db ’Witaj swiecie!’,0
section.textglobal adres
adres: lea eax,[hello]ret
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Komunikacja z programami w jezyku C
A teraz czesc w C
#include <stdio.h>
extern char *adres(void);
int main(){printf("%s\n", adres());return 0;
}
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Przydatne instrukcje
Popatrzmy jeszcze na kilka mniej znanych instrukcji.Zaczniemy od instrukcji petli.W dotychczasowych przykładach do sterowania iteracjauzywalismy porównan w połaczeniu ze skokamiwarunkowymi.Zamiast tego mozna uzyc instrukcji loop i jej odmian:
W rejestrze licznika ecx/rcx ustawiamy liczbe iteracji.Petle rozpoczynamy etykieta, np. iter1Na koncu petli umieszczamy instrukcje
loop iter1
Petla wykona sie tyle razy, ile wynosiła wartosc licznika(ale co najmniej raz!).
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Przykład: inicjowanie bufora (od tyłu)
mov ecx,rozmiarmov eax,wartoscjecxz dalej
iter:mov [bufor-4+ecx*4],eaxloop iter
dalej:
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Przykład: szukanie konca napisu z C
mov ecx,100 ;długosc buforamov ebx,0 ;poczatkowy indeks
iter:mov al,[bufor+ebx] ;kolejny znakinc ebxcmp al,0loopne iterje znaleziono
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Pobieranie adresu efektywnego
Przy wywołaniach systemowych czesto argumentem jestadres.Nie zawsze jest on stała, czasem powstaje np. przezzsumowanie adresu poczatku i indeksu znajdujacego sie wrejestrze.Wymaga to obliczenia adresu efektywnegomov ecx,buforadd ecx,esi ;Indeks mamy w ESI
Ten sam efekt mozna uzyskac instrukcja lea. Wyznaczaona adres efektywny swojego drugiego argumentu, poczym umieszcza ten adres w rejestrze podanym jakopierwszy argumentlea ecx,[bufor+esi]
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Pobieranie adresu efektywnego
Uzywajac zaawansowanych skalowanych trybów adresowychprocesora Pentium mozna czesto w ten sposób obliczac wjednym cyklu złozone wyrazenia, np.
lea eax,[edx*4 + edx + 7]
powoduje umieszczenie w rejestrze eax wartosci wyrazenia 5* edx + 7. W NASM mozna zreszta te instrukcje zapisacjeszcze prosciej
lea eax,[edx*5 + 7]
ale to juz specyficzne obczujnienie parsera instrukcji.
Uwaga: instrukcja lea nie ustawia flag.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Rozszerzanie
Czesto w programie chcemy rozszerzyc argument, np.załadowac bajt z pamieci do rejestru czterobajtowego.W przypadku gdy argument zawiera liczbe nalezy uzycinstrukcjimovsx 〈rejestr〉,〈rejestr-lub-pamiec〉Instrukcja ta rozszerza prawidłowo znak argumentu, np.jesli rejestr ax zawiera liczbe -2345, to po wykonaniuinstrukcjimovsx ebx,ax
równiez rejestr ebx bedzie zawierał -2345 (alereprezentowane na 32 bitach).
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Rozszerzanie
Jesli argument nie zawiera liczby (np. jest to kod ASCIIznaku), to nalezy uzyc instrukcji movzx, np. jesli rejestr alzawiera wartosc 177 (kod litery a w kodzie 8859-2), to abyprzepisac ja do rejestru ebx uzyjemymovzx ebx,al
Instrukcja ta dodaje zawsze na poczatku zera.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Sprawdzanie i ustawianie pojedynczych bitów
Podstawowe instrukcje słuzace do ustawiania flagwarunków to test i and.W procesorach Pentium dodatkowo wystepuje instrukcjabt zródło,numer-bitu
przepisujaca ze zródła wskazany numerem bit do flagi CF.Numer bitu moze byc podany stała bajtowa lub rejestrem.Jesli zródło jest rejestrem, to numer bitu nie moze bycwiekszy niz rozmiar rejestru, natomiast jesli jest to adres wpamieci, to nie ma takich ograniczen.Ułatwia to implementacje tablic bitowych.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Sprawdzanie i ustawianie pojedynczych bitów
Oprócz instrukcji bt istnieja instrukcje btc, bts i btr,słuzace do ustawiania pojedynczych bitów.Przydaja sie przede wszystkim do realizacji mechanizmówsynchronizacji, takich jak semafory.Nalezy pamietac, ze dla rejestrów instrukcja bt jestwolniejsza niz test.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Instrukcje blokowe
Instrukcje blokowe słuza do szybkiego przetwarzaniaciagów bajtów (lub wiekszych jednostek), np. do szybkiegoprzeniesienia zawartosci fragmentu pamieci ekranu w innyobszar.Zasady:
adres poczatku bloku zródłowego umieszczamy wrejestrach ds:esi,adres poczatku bloku docelowego umieszczamy wrejestrach es:edi,długosc bloku podaje rejestr ecx (w jednostkachodpowiednich do uzywanych instrukcji: bajtach, słowachitd.),kolejne dane przechodza przez rejestr al (lub ax, eax).
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Instrukcje blokowe
Przykład: wypełnienie bufora ekranu o adresie podanym wedi znakiem i atrybutem, podanymi w rejestrach al i ah(mozna te technike zastosowac do bezposredniegooperowania na fizycznej pamieci ekranu, ale zwykle wLinuksie nie mamy do tego dostatecznych uprawnien).Bez instrukcji blokowych mozna to zrobic nastepujaco:
fill: push ecxpush edimov cx,25*80
fill1: mov [edi],axinc ediinc ediloop fill1pop edipop ecxret
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Instrukcje blokowe
Uzyjemy teraz instrukcji stosw, która zapisuje zawartoscrejestru ax do komórki pamieci o adresie podanym w edi,po czym automatycznie zwieksza edi o 2.fill: push ecx
push edimov cx,25*80cld
fill1: stoswloop fill1pop edipop ecxret
Instrukcja cld ustawia flage kierunku DF w procesorze.Stan tej flagi decyduje o kierunku kopiowania (dla zeraadresy sa zwiekszane).
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Instrukcje blokowe
Aby jeszcze bardziej uproscic nasz program mozemyskorzystac z przedrostka rep.Jego uzycie powoduje wielokrotne wykonaniepoprzedzonej nim instrukcji z kazdorazowymzmniejszaniem rejestru ecx.Zakonczenie nastepuje po wyzerowaniu rejestru ecx.
fill: push ecxpush edimov ecx,25*80cldrep stoswpop edipop ecxret
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Instrukcje blokowe
Inny przykład: nalezy przekopiowac ciag 60 bajtów, któregoadres poczatkowy znajduje sie w esi w do bufora o adresiepodanym w edi (zakładamy, ze obszary nie nakładaja sie).
copy: pushfpush eaxpush ecxpush esipush edimov ecx,60cldrep movsbpop edipop esipop ecxpop eaxpopfret
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Instrukcje blokowe
Uwaga: w ostatnim przykładzie zachowujemy poprzedni stanflagi DF na stosie (wraz z innymi flagami procesora). Jest towymagane w programach systemowych (zwłaszczaobsługujacych przerwania) i procedurach bibliotecznych.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Wstawianie pliku
Do tekstu programu mozna w trakcie asemblacji właczaczawartosc dodatkowych plików, np. zawierajacych definicjeczesto uzywanych stałych i makr.Robi sie to poleceniem %include, np. aby wstawiczawartosc pliku moje-makra.asm piszemy%include "moje-makra.asm"
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Makra
Makra w asemblerze NASM dziela sie na jedno iwielowierszowe.Zasada działania jest podobna: makrowołanie w teksciejest w czasie asemblacji zastepowane rozwinieta postaciamakra — jego trescia.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Makra
Makra jednowierszowe odpowiadajace wyrazeniomdefiniuje sie poleceniem %define.Najprostsze makra jednowierszowe to definicje stałych, np.%define TCGETS 0x5401
Poczawszy od tego miejsca w programie wszystkiewystapienia symbolu TCGETS zostana tekstowozastapione stała 0x5401.Oczywiscie ten sam efekt mozna osiagnac korzystajac zpolecenia equ.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Makra
Definicja stałej moze byc jednak bardziej złozona, np.stanowic ciag elementów składniowych%define CTRL 0x1F &
W tym przypadku wierszmov byte [ebx+4], CTRL ’D’
zostanie zastapiony przezmov byte [ebx+4], 0x1F & ’D’
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Makra
Makra jednowierszowe moga miec parametry.Kazdy parameter w definicji makra zastapiony zostanietekstowo argumentem makrowołania, np. dla makra%define param(n) ([ebp + 4 * (n) + 4])
wierszmov edx,param(2)
zostanie zastapiony przezmov edx,[ebp+12]
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Makra
Nawiasy uzyte w makrodefinicji zapobiegajanieodpowiedniej kolejnosci obliczania.Generalna zasada: otaczamy nawiasami cała tresc makra,a wewnatrz niej otaczamy nawiasami kazde wystapienieparametru.Czasami niektóre nawiasy mozna pominac, np. w naszejdefinicji zewnetrzna para nawiasów jest zbedna.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Makra
NASM dopuszcza przeciazanie (overloading) makr –definiowanie tych samych makr z inna liczba parametrów.Pozwala to uzywac argumentów domyslnych, np.%define zwieksz(x) ((x) + 1)%define zwieksz(x,y) ((x) + (y))
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Makra
Makra wielowierszowe definiuje sie poleceniem %macro.Ich makrowołania zastepowane sa ciagami instrukcji ipolecen.Najprostsze sa makra bezparametrowe, np. zakonczeniepracy programu%macro exit 0
mov eax,1int 0x80
%endmacro
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Makra
Tak zdefiniowanego makra mozna uzyc w programie jakonowej „instrukcji”
...exit...
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Makra
Makroinstrukcja zerowania rejestru wymaga juz parametru%macro clr 1
xor %1,%1%endmacro
i moze byc wywołana nastepujaco...clr eax...
Argument w nagłówku makrodefinicji podaje liczbeparametrów, do kolejnych parametrów odwołujemy sie wtresci piszac %1,%2,....
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Makra
Podobnie dla standardowego poczatku procedury mozemyzdefiniowac jednoargumentowe makro prolog
%macro prolog 1push ebpmov ebp,esppush ebxpush esipush edisub esp,%1 ;rezerwacja na stosie podanej liczby bajtów
%endmacro
Tak zdefiniowanego makra mozna uzyc piszacmojafunkcja: prolog 12
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Makra
%0 oznacza liczbe podanych parametrów i moze bycwykorzystany np. przy asemblacji warunkowej (zob. dalej)
...%rep %0
...%endrep
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Makra
W bardziej złozonych makroinstrukcjach (np.zawierajacych petle) moga byc potrzebne etykiety.Przy wielokrotnym wystapieniu makrowołania w kodziepowodowałoby to bład powtórzenia symbolu, dlategoetykiety lokalne w tresci makra nalezy poprzedzacznakami %%.Podczas kazdego rozwijania makra asembler wygenerujew ich miejsce nowe, unikalne nazwy%macro abs 1
cmp %1,0jge %%skipneg %1
%%skip:%endmacro
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Makra
Ostrzezenie: makra sa niebezpieczne
Złozone makra czesto uzywaja dodatkowych rejestrów,których nie widac w makrowołaniu. Łatwo wtedyzapomniec o ich zachowywaniu.W jezykach wyzszego poziomu czasem uzywa sie makrzamiast procedur po to, aby miec dostep do „nielokalnych”zmiennych.W asemblerze nie ma takiej potrzeby („wszystko widac”),wiec nie nalezy uzywac makr zamiast procedur.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Asemblacja warunkowa
Asemblacja warunkowa pozwala z tego samego tekstugenerowac programy binarne na rózne srodowiskaobliczeniowe, np. rózne wersje systemu operacyjnego.Jednak najczestsze wykorzystanie to właczenie do tekstudodatkowych instrukcji, uzywanych tylko podczasuruchamiania programu.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Asemblacja warunkowa
Zwykle uzywa sie do tego symbolu DEBUG i konstrukcji%ifdef 〈symbol〉〈ciag instrukcji〉%endif
Jesli 〈symbol〉 jest zdefiniowany, to 〈ciag instrukcji〉zostanie przetworzony i właczony do programu, wprzeciwnym razie bedzie pominiety, np.%ifdef DEBUG
call wypisz_stan%endif
spowoduje wywołanie procedury wypisz_stan tylko jesliw trakcie asemblacji zdefiniowany był symbol DEBUG.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Asemblacja warunkowa
Ogólniejsza konstrukcja do asemblacji warunkowej jest%if 〈warunek〉...%elif 〈warunek〉...%else...%endif
Oczywiscie 〈warunek〉 sprawdzany jest w trakcieasemblacji.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Asemblacja warunkowa
Inna wygodna konstrukcja jest iteracja%rep 〈n〉...%endrep
Powoduje ona 〈n〉-krotne przetworzenie swojej tresci.Uzywajac powyzszych konstrukcji mozna wypełnic obszardanych kolejnymi liczbami całkowitymi.%assign kolejna 0%rep 64
dd kolejna%assign kolejna kolejna + 1%endrep
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Asemblacja warunkowa
Konstrukcja %assign pozwala nadawac i zmieniacwartosci zmiennym asemblera, tak jak w powyzszymprzykładzie.W odróznieniu od stałych definiowanych przez %definewartosc jest natychmiast obliczana i musi byc liczba.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Asemblacja warunkowa
Do wczesniejszego wyjscia z petli %rep słuzy %exitrep,np....%if suma > 65000%exitrep%endif...
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Struktury danych (rekordy)
Strukturalne typy danych (zwane tez rekordami)definiujemy uzywajac konstrukcji:
struc 〈mój_typ〉〈pole1〉: resb 1
...endstruc
Powoduje to utworzenie stałych o nazwach 〈pole1〉,...Wartoscia kazdej z nich jest offset – odległosc poczatkupola od poczatku struktury.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Struktury danych (rekordy)
Obiekty zdefiniowanego typu deklarujemy uzywajacpolecenia istruc:〈mój_obj〉: istruc 〈mój_typ〉
at 〈polei〉, db 〈wartosc_poczatkowa〉...iend
Opcjonalne polecenia at słuza do inicjowania pól, musibyc przy tym zachowana kolejnosc pól z definicji.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Struktury danych (rekordy)
Do pól rekordu odwołujemy sie przez offset 〈typ〉.〈pole〉 lubpo prostu 〈pole〉, np.
mov eax,[ebx + 〈pole〉]Oczywiscie nie ma prawie zadnej kontroli zgodnosci typów.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Asembler Gnu (gas)
Asemblacja:as hello.s -o hello.o
Linkowanie (jesli uzywamy bibliotek):ld -dynamic-linker /lib/ld-linux.so.2 -o hello hello.o -lc
Dla bibliotekild -shared -o hellolib.so hello.o
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Składnia AT&T (z kregów Unixa)
Nazwy rejestrów poprzedzane znakiem ‘%’, np. %eax,%dl. Dzieki temu w programach w asemblerze moznauzywac dowolnych identyfiaktorów z jezyka C, bezpoprzedzania ich znakiem podkreslenia.Kolejnosc argumentów dla instrukcji binarnych: najpierwargument zródłowy, potem wynikowy, odwrotnie niz wasemblerach „intelowskich”. Np. instrukcja zapisywana wNASM jako
mov eax,edx
bedzie w GAS zapisana jakomovl %edx, %eax
Komentarze poprzedzane znakiem ‘#’.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Składnia AT&T (z kregów Unixa)
Rozmiar argumentów zapisywany musi byc podanysufiksem w mnemoniku operacji: b dla bajtu (8 bitów), wdla słowa (16 bitów), l dla long (32 bity) oraz q dla quad(64 bity). Np. zamiast mov piszemy movl dla rejestrów edxi eax.Argumenty bezposrednie (stałe i wskazniki) nalezypoprzedzac prefiksem $, np.
movl $5,%eax
Pominiecie prefiksu $ oznacza potraktowanie argumentujako adresu, np.
movl licznik,%eax
umieszcza zawartosc zmiennej licznik w rejestrze eax.
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Składnia AT&T (z kregów Unixa)
Nawiasy uzywane sa tylko dla rejestrów adresowych,indeksowania itp.
testb $0x80,17(%ebp)
Inny zapis trybów indeksowych. Zapis w GASiemovl %eax,8(%ebx,%edi,4)
odpowiada w NASMiemov [8 + ebx + 4 * edi],eax
Składnia GASa to:stały-adres(rejestr-przesuniecia,rejestr-indeksowy,rozmiar-
elementu)Zbedne rejestry pomijamymovl dane(,%edi,4),%eax
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Dyrektywy gas
Nazwa zawsze zaczyna sie kropka.Właczanie pliku:
.include łinux-calls.s"
Deklaracja sekcji podobna.section .text
Definiowanie stałych:.equ ile,15
helloworld:.ascii "hello world\n"
helloworld_end:equ helloworld_len,helloworld_end - helloworld
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk
Dyrektywy gas
Symbole globalne (eksport):.globl _start
Rezerwacja pamieci (w .bss):.lcomm <nazwa>,<rozmiar>
Rezerwacja pamieci z inicjowaniem:.ascii "To jest napis\n\0"
.byte 10,12,4
.int 234,1487
.long 2345,-345
Repetycja:.rept 50.byte 1,2.endr
Deklaracja typu symbolu:.type <symbol>,@function
Zbigniew Jurkiewicz, Instytut Informatyki UW Programowanie w asemblerze Asembler i jego jezyk