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