1 Funkcje i procedury

Transkrypt

1 Funkcje i procedury
1
Funkcje i procedury
Chcemy symulowa¢ w asemblerze deniowanie funkcji i procerur. Jak to robi¢? Rozwa»my przykªad:
int funkcja (int n){
int i,j;
(...)
return j;
}
main () {
int i,j;
i=funkcja(i);
...
j=funkcja(i);
}
.
Problemy:
1. funkcja operuje na pewnych rejestrach, by¢ mo»e na tych samych co program gªówny
2. po skoku do funkcji musimy wróci¢ do miejsca z którego skakali±my funkcja jest wywoªywana z ró»nych
miejsc; musimy zapamietac adres powrotu
3. do funkcji w jaki± spósob musimy przekaza¢ parametry i w jaki± sposób musimy otrzyma¢ wyniki.
W przypadku MIPSa przyj¦ta konwencja jest nast¦puj¡ca: rejestry $a0 - $a3 przechowuj¡ argumenty
wywoªania (w przypadku wi¦kszej liczby argumentów u»ywamy stosu); rejestry $v0, $v1 przechowuj¡ zwracane
wyniki
Przykªad: ªadujemy parametr do $a0: add $a0, $zero, $s3 (zakladamy, ze parametrem jest $s3). Nie
mo»emy niestety po prostu skoczy¢ j FUNKCJA, bo nie wiedzieliby±my gdzie wroci¢. MIPS ma jednak podobny
rozkaz do rozkazu MARIE JnS. Rozkaz jal FUNKCJA (typu J) skoczy do adresu FUNKCJA i dodatkowo zapami¦ta
w specjalnym rejestrze $ra adres powrotu.
Po jal FUNKCJA u»yjemy zapewne czego± w stylu: add $s7, $zero, $v0, aby przechowa¢ zwrócon¡ warto±¢.
Przyjmijmy, »e po etykiecie FUNKCJA, b¦dziemy u»ywa¢ rejestrów $s0,$s1,$s2. Te rejestry mog¡ by¢ te»
u»yte w programie gªównym. W jaki± sposób nale»y zatem przechowa¢ ich warto±ci. Do tego celu u»yjemy
stosu. MIPS ma specjalny rejestr $sp - wska¹nik stosu. Nie ma specjalnych rozkazów operuj¡cych na stosie musimy sami dba¢ o szczegóªy. Po wstawieniu elementu na stos zmniejszmay stos o 4, po zdj¦ciu zwi¦kszamy
o 4(stos ro±nie w dóª)
Teraz co si¦ dzieje za etykiet¡ funkcja Wracamy do przykªadu:
FUNKCJA: addi $sp, $sp, -12
sw $s0, 8($sp)
sw $s1, 4($sp)
sw $s2, 0 ($sp)
Przed powrotem do programu glównego funkcja odtwarza zawartosc rejestrów (ª¡cznie z rejestrem wskazuj¡cym stos):
lw $s2, 0($sp)
lw $s1, 4($sp)
lw $t0, 8($sp)
addi $sp, $sp, 12
jr $ra #powroc do miejsca wywolania
Uwaga: jr jest typu-R, a nie typu J
Uwaga: zakªadali±my caªy czas, »e funkcja nie wywoªuje innych funkcji, dlatego te» np. nie musieli±my
zapami¦tywa¢ na stosie parametrów wywoªania.
1
Komentarz: Przedstawiona strategia zapami¦tywania warto±ci na stosie jest jedn¡ z mo»liwych, nie jedyn¡,
w dodatku nie najcz¦±ciej u»ywan¡. W naszynm przykªadzie - wszystkie czynno±ci s¡ wykonywane przez strone
wywoªywan¡. Inne mo»liwe rozwiazanie wszysko przez stron¦ wywolujac¡. W praktyce: cz¦±¢ rzeczy robi
strona wywoªuj¡ca, cz¦±¢ wywoªywana. Dokªadniej: strona wywoªuj¡ca zapami¦tuje sobie wszystkie rejestry
tymczasowe ($ti)- strona wywolywana zakªada, »e mo»e je zmienic, ale nie moze ruszyc $si, je±li wi¦c chce z
nich korzysta¢ musi zachowa¢ ich warto±ci.
2
Przykªad procedury rekurencyjnej
Zadanie: zsumowa¢ liczby z przedziaªu 1 do n.
sumton:
rec:
main:
addi
sw
sw
bne
addi
lw
$sp,$sp,-8
$ra,4($sp)
$a0,0($sp)
$0,$a0,rec
$v0,$zero,0
$ra,4($sp)
#
#
#
#
#
#
#
#
addi $sp,$sp,8
#
jr
$ra
#
addi $a0,$a0,-1
#
jal sumton
#
lw
$a0,0($sp)
#
#
add $v0,$a0,$v0
#
lw
$ra,4($sp)
#
addi $sp,$sp,8
#
jr
$ra
#
addi $a0,$zero, 10 #
jal sumton
addi $a0, $v0, 0 #
li
$v0, 1
#
syscall
#
miejsce na dwa elementy na stosie
odkladamy adres powrotu
odkladamy argument
skocz do rec jesli argument rozny od 0
ustawiamy wynik na 0
odtworzenie adresu powrotu
(w tym miejscu niekonieczne, ale
tak jest bardziej elegancko...)
zwalniamy dwa miejsca na stosie
powrot z funkcji
n := n-1
wywolanie z parametrem n-1
odtworzenie a0
w $v0 jest wynik sumton(n-1)
$v0 = n + sumton(n-1)
odtworzenie adresu powrotu
zwalniamy dwa miejsca na stosie
powrot z funkcji
wywolanie z parametrem 10
wypisanie wyniku
wypisanie wyniku
wypisanie wyniku
Ostanie linie w programie to wywoªanie funkcji sysemowej wypisuj¡cej na wyj±cie liczb¦ caªkowit¡.
3
Inne rozkazy
Dotychczas operowali±my na sªowach. Istniej te» dost¦p do poszczególnych bajtów.
lb s2, 3(s1) - load byte rozkaz typu I kopiuje bajt o podanym adresie do 8 najmniej znacz¡cych bitów
rejestru i wypeªnia reszt¦ rejestru najbardziej znacz¡cym bitem bajtu (dziaªa przy reprezentacji uzupeªnie«
do 2, je±li chcemy uzupeªni¢ zerami u»ywamy lbu load byte unsigned). sb s2 − 2(s1) - store byte - kopiuje
8 najmniej znacz¡cych bitów rejestru. Zazwyczaj u»ywane do operacji na tekstach.
Przykªad programu licz¡cego dªugo±¢ tekstu:
.data
str1:
.asciiz "Przykªadowy napis."
.text
.align 2
.globl main
strlen:
loop
addi $v0, $zero, 0
: lb
$t0, 0($a0)
beq
$t0, $zero, EXIT
addi $a0, $a0, 1
# -v0 - licznik
2
EXIT
main:
addi $v0, $v0, 1
j
loop
jr
$ra
(...)
la
$a0, str1
jal
strlen
(...)
Zestaw operacji bitowych: and, or, nor, andi, ori, nor, xor, xori.
W jaki sposób zaªadowa¢ do rejestru konkretny wzorzec bitowy, np. 0x5467a7ba? Nie mo»e by¢ jednej
instrukcji - 32 bity! Rozwi¡zanie wykorzystuje rozkaz lui load upper immediate
lui $t0, 0x5467
# ni»sze bity rejestru ustawia na 0.
ori $t0, $t0, 0xa7ba
Operacje przesuni¦cia: sll $t0, $t1, 7 , srl (dopeªnia zerami) rozkazy typu R - przesuwamy o maksymalnie 32 pozycje przesuni¦cie kodowane w polu shamt, (jeden rejestr wolny).
Mno»enie: mult s0,s1.- 64 bity wyniku. Wynik zapisywany w rejestrach HI i LO. Bardziej znacz¡c¡
cz¦±c wyniku mo»na uzyska¢ rozkazem mfhi $t0, mniej znacz¡c¡: mflo $t1.
Jak ju» wspomnieli±my istnieje pseudorozkaz mul r1, r2, r3 zapisywana jest mniej znacz¡ca cz¦±c
wyniku
Dzielenie: div s2,s3. Wynik w rejestrze LO, reszta z dzielenia w rejestrze HI.
3.1
Liczby zmiennopozycyjne
Operacje na liczbach zmiennopozycyjnych s¡ zupeªnie inne od tych na caªkowitych. Mamy wi¦c inne rozkazy
oraz specjalny zestaw rejestrów zmiennopozycyjnych - $f0, $f31. Jednostka zmiennopozycyjna nazywana jest
koprocesorem 1.
Rozkazy add.s, sub.s, add.d , sub.d (format R). - pierwsze dwa single, pozostaªe - double Uwaga: rejestry
s¡ 32-bitowe, a format zmiennopozycyjny double 64-bitowy. W przypadku double warto±ci przechowywane s¡
w parach rejestrów odwoªujemy si¦ tylko do rejestrów parzystych.
Musz¡ by¢ nowe rozkazy przesyªania - 32 rejestry - 5 bitów! lwc1 $f1, 40($s1) , swc1 (c1 to skrót od
corpcessor 1).
Przykªad wczytywania liczb zmiennopozycyjnych:
.data
floats:
.float -0.123, 3.14
W programie: lwc1
lwc1
$f0, floats
$f1, floats + 4
Dla liczb zmiennopozycyjnych s¡ osobne rozkazy skoku:
c.eq.s $f1, $f4
bc1t
Label
bc1f
Label2
Je±li rejestry $f1 i $f2 przechowuj¡ t¡ sam¡ warto±¢ to skocz pod Label, w przeciwnym wypadku pod Label2.
(wynik porównania w specjalnym jednobitowym rejestrze niedost¦pnym dla programisty).
Mno»enie mul.s $f0, $f1, $f2 div.s .....
3.2
Funkcje systemowe
Do realizacji operacji wej±cia wyj±cia najpro±ciej u»ywa¢ gotowych funkcji systemowych (wywoªywanych poleceniem syscall.
1. Print an Integer ($a0 = warto±¢ do wydrukowania)
3
2. Float
3. Print Double
4. Print String ($a0 = adres napisu)
5. Read an Integer (wczytany wynik zwracany w $v0)
6. Read Float
7. Read Double
8. Read a String ($a0 = adres pod jaki nale»y wpisa¢, $a1 = dªugo±¢ przydzielonej pami¦ci)
3.3
Dodatkowe informacje
Polecam stron¦ symulatora SPIM http://www.cs.wisc.edu/~larus/spim.html, w szczególno±ci dodatek do
ksi¡»ki Hennessy'ego i Pattersona Computer Organization and Design: The Hardware/Software Interface:
http://www.cs.wisc.edu/~larus/HP_AppA.pdf
4

Podobne dokumenty