Laboratorium AK –ATT asembler (Debian LINUX)
Janusz Biernat,
pa dziernik 2007
1
(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
(
)
)
*
)
+ , $
*
)
)
(
)
$
-./0/*
'
'&
1
+ , $
11 2
3
&
'
&
11 2
3
&
'
&
11 2
3
&
'
&
11 2
3
&
'
&
(
)
*
*
)
)
(
$
opcja uruchomienia z poziomu kompilatora C++ (etykieta startowa:
4
– jak w C a nie
4
)
(
(
)
*
5 , $
*
)
)%
' '
56
)%
'
78
'
9
'
: ; <==
&
'
>(
tworzenie pliku wsadowego: asemblacja-ł
czenie
!
&
'
' '
*
)
'$
&
(
)
) *
)
'$
&
&
(
)
)
$3
& *
$3
& *
$3
& *
$3
& *
'
'
'
&
$3
$
'
&
$
&
'
,
&
?
6
&
'
7
6
$ &
@'
A
! !
B
&
' 5 , $
!
)C
$3
*
$3
*
$3
*
$3
*
@
! '
B
'
'$
&
)
A
)
A
)
A
)
A
&
&6
&
&
&6
$3
&
A
@
B
Laboratorium AK –ATT asembler (Debian LINUX)
Janusz Biernat,
pa dziernik 2007
2
Struktura programu w j zyku asemblera ATT (linux-asm dla x86/Pentium)
Zapis stałych i znaków specjalnych
7 : "">D:E
>D:E
$
3
7
'
7: ;
&
7:A(D
(D
$
A
"
7: :E:E
:E:E
$
,&
"
7:!(FEG =HI(<
(FEG =H AE:
<
$
!
znaki specjalne (\ =”escape” – nast
pny znak specjalny) – konwencja UNIX / LINUX
J
!
/C KK
,
JALL
LL
/C KK
: ; H / ;M
J:
'
J
N
J:A:/
J:E<
J
O/P
J:A:H
J:EE
J
J:A:>
J:E:
J!
MM
!
!
J:A:
J:EG
J
Q
'
J:A:L
J:E=
J;
&
) JJ
J
JB
B
) R' S/N
@
B
S/N
)
S/N T
S/N
)
)
A
U
&
3
'5
S/N
' 7
Dyrektywy organizacyjne
)
"
/ I
&
6
'
&
/ I
)
" )
A
'
'
'
&
6
)
N/PIN
3
)
&
)
4
V4
6
4
4
)
! W!'
&
!'
&
3
&
)
&
)
!
!'
&
)
&
)
" )
'
&
)
" )
'!
&
)==%XE E"
) R' P-M4CKYI
'
'
,
'
EX :::)
)
/LLQ
P-M4CKYI
'&
'&
P-M4CKYI
& ,
3
)
'!
'
&6
' /LLQ
)
'
MKNI
!
&
3
'
')
Rezerwacja bufora w pami
ci (w sekcji danych)
* )
BZ J B
$ 9 '
,
/C KK
A * )
T
A * )
@J B
.ascii “STRNG” zamienia ka
dy znak ła
cucha (“STRNG”) na bajt kodu ASCII
*
&
&
'
@
B
)
#
E #
< ;
&
&
& ,
6
)
#
E #
< ;
&
&
G(
&
$,
6
4
T) (
&
&
' @7B
Laboratorium AK –ATT asembler (Debian LINUX)
Janusz Biernat,
pa dziernik 2007
3
*
&
'!
3
@
B
)
num [, fill]
num – rozmiar w bajtach, fill – opcja: warto
wypełnienia (domy
lnie 0),
*)
równowa
na dyrektywa: )
num [, fill]
)
)
V)
&
&
)
!
)DF%DH E"
)
Zmienna i jej adres
# ?
A
@
B
&
'
# ?
A
7
& @
B
&
'
Funkcje standardowe – syscall (linux-asm dla x86/Pentium)
!'
&
?
A
* ?
A
?
A
?
A
@ A
A
A
A
B
6
9
'
I[KO T E
!'
&
'
TE
#
7 '
?
A"
?
A
'
@
7B
?
>
5
,
#
7I[KO
?
A
'
!'
&
TE
?
A
7:A>:
,
$
!'
&
@
B
!'
&
@
,
&
V
B
COLK
T :
&
'
?
A
QI/L T F
!'
&
&
TF
)
)
'!
&
P-M\Q*
;
&
&
'!
&
P-M4CKYI T)( P-M\Q
)
)
A
'5
!'
&
QI/L
;
#
7P-M4CKYI
?
A
'!
&
7P-M4CKYI
?
A
#
7P-M\Q
?
A
'!
7P-M\Q
?
A
#
7COLK
?
A
&
?
A
COLK T:
#
7QI/L
?
A
!'
&
?
A
TF
7:A>:
@
B
!'
&
@
&
V
B
COL\-O T E
&
?
A
.QKOI T G
!'
&
&
TG
)
)
A
'5
!'
&
.QKOI
;
#
7P-M4CKYI
?
A
'!
&
7P-M4CKYI
?
A
#
7P-M\Q
?
A
'!
7P-M\Q
?
A
#
7COL\-O
?
A
&
?
A
COL\-OTE
#
7.QKOI
?
A
!'
&
?
A
TG
7:A>:
Laboratorium AK –ATT asembler (Debian LINUX)
Janusz Biernat,
pa dziernik 2007
4
Najwa niejsze funkcje systemu Linux
O
(E) K
N
'A C
E"
%eax
nazwa
%ebx
%ecx
%edx
Uwagi
1 exit
status (int)
Zako
czenie programu
3 read numer pliku
1)
adres bufora
rozmiar bufora
Odczytuje plik do wskazanego bufora.
4 write numer pliku
1)
adres bufora
rozmiar bufora
Zapisuje z bufora do danego pliku.
5 open nazwa pliku
2)
lista opcji
3)
kod zezwole
(lub 0666)
Otwiera plik o podanej nazwie. Zwraca
numer pliku (w %eax) lub kod bł
du.
6 close numer pliku
1)
Zamyka plik o danym numerze.
12 chdir nazwa katalogu
4)
Przeł
cza do wskazanego katalogu.
19 lseek numer pliku
1)
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 katalogu
4)
kod zezwole
Tworzy katalog, zakładaj
c
e katalogi
nadrz
dne (
cie
ka) ju
istniej
.
40 rmdir nazwa katalogu
4)
Usuwa katalog.
41 dup
numer pliku
1)
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.
Laboratorium AK –ATT asembler (Debian LINUX)
Janusz Biernat,
pa dziernik 2007
5
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.
Laboratorium AK –ATT asembler (Debian LINUX)
Janusz Biernat,
pa dziernik 2007
6
U ycie debuggera gdb (linux-asm dla x86/Pentium)
B
B
!
'
'
((
(
)
)
&
((
)
(
)
$
(
)
&
)
'
5
)%
)%
' '
'
6
'
&3
&
" A
'
'$
&
' A
A
T
V
V
4!'
&
A
'$
&
' A
A
;
'$
&
' A
;
'
A
;
'$
&
' A
;
'
'
,
'$
&
'
' "
' '
$
'
'
;
(
&
'&
3
&
3
'
* @C
;B
@2
#
CK0K O
K
'
)B
"
.
*
4
'
&
&3
A "
!'
&
&
&
'
& 1
!
"
&
&
%
!
7
&
?
7
1
!
!
*
3
A
,
!
A%
!
&
3
&
,$ $
$
' $
!
!
&
5 &
5
T
'
&
TE
T
5
6
%
!
7
&
5
&
'$
%
,
3
'
$ 9 '
/C KK
! "
!
&
*
&
3
! "
!
&
&
! "
!
&
'
'$
"
'
"
9
'
'
]
R'
&
'
'
Laboratorium AK –ATT asembler (Debian LINUX)
Janusz Biernat,
pa dziernik 2007
7
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
(1 linia w dół) /
[k] –
↑
1
(1 linia w gór
)
[-] –
←←↑
1
(pocz
tek wiersza, linia w gór
)
[+] –
←←↓
1
(pocz
tek wiersza, linia w dół =
↵
↵↵
↵
)
[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
Laboratorium AK –ATT asembler (Debian LINUX)
Janusz Biernat,
pa dziernik 2007
8
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
Laboratorium AK –ATT asembler (Debian LINUX)
Janusz Biernat,
pa dziernik 2007
9
Przykładowe programy
Szukanie maksimum [1]
2-Q2\CI* O
!
A
'
'
!
!
)
?
( Z
A
!
A
?
A ( N
! '
?
A (
'
O
!
'
*
4
(
) / :
'
)
)
4
*
O
)
F XD FG <<< G= D= =G FG GG FF << EE XX :
)
)
A
)
4
4
*
#
7:
?
#
:
A
#
4
?
G
?
A
!
!
#
?
A
?
A
!
?
A
4
*
7:
?
A
!
^#
&
4 A
?
A
#
'
#
4
?
G
?
A
?
A
?
A
#
'
&
4
&'
!
^
#
?
A
?
A
#
#
'
&
4
&'
4 A
*
?
A
'
!
A
A
'
'
#
7E
?
A
E
A
7:A>:
Kompilacja i konsolidacja (Now, assemble and link it with these commands):
A
' )
(
A
' )
A
' )
(
A
'
Uruchomienie i sprawdzenie statusu (Now run it, and check it’s status).
)%
A
'
)% (
56
78
Laboratorium AK –ATT asembler (Debian LINUX)
Janusz Biernat,
pa dziernik 2007
10
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
Laboratorium AK –ATT asembler (Debian LINUX)
Janusz Biernat,
pa dziernik 2007
11
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)
Laboratorium AK –ATT asembler (Debian LINUX)
Janusz Biernat,
pa dziernik 2007
12
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,
Laboratorium AK –ATT asembler (Debian LINUX)
Janusz Biernat,
pa dziernik 2007
13
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
Laboratorium AK –ATT asembler (Debian LINUX)
Janusz Biernat,
pa dziernik 2007
14
Funkcja rekurencyjna – powroty (zwalnianie stosu)
nx_ad:
%ebp”
esp*
# omini te
movl 8(%ebp), %ebx
nx_ad
# omini te
%eax”
[ebp+8]
→
ebx
# omini te
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….)