Architektura komputerów lab2 PT17 TP Kukulski Tchorowska, Studia, PWR, 4 semestr, Architektura komputerów 2, laboratoria


Zespół: PT/17/TP Wrocław, 26.03.2010

Elżbieta Tchorowska, 171067

0x08 graphic
Konrad Kukulski, 163930

0x08 graphic
Ocena:

Oddano:

Pętle w programach asemblerowych na platformie Linux

Sprawozdanie z laboratorium z przedmiotu „Architektura Komputerów”

Rok. Akadem. 2009/2010, Kierunek: INF

PROWADZĄCY:

Mgr inż. Mariusz Czapski

Spis treści:

Cel ćwiczenia

Celem ćwiczenia było zapoznanie się ze strukturą pętli w programach asemblerowych i nauka jej wykorzystywania, przy formatowaniu tekstu. Zadaniem było zmodyfikowanie programu z ostatnich laboratoriów, który prosił o podanie ciągu znaków, na taki, który po otrzymaniu tego ciągu wypisze je na ekranie, dzieląc na trzy rzędy.

Przebieg ćwiczenia

Głównym materiałem był plik tekstowy z programem z poprzedniego tygodnia, który prosił o podanie imienia, poczym wypisywał je ponownie. Program wyglądał następująco:

0x08 graphic

I jego działanie zostało dokładniej opisane w poprzednim sprawozdaniu. Wygląd pliku Makefile, pomija się i przyjmuje, że jego działanie jest wiadome.

Algorytm

Celem przypomnienia: zadaniem było utworzenie trzech rzędów, gdzie w każdej miał znajdować się co trzeci znak wprowadzony z ekranu przez użytkownika. Np. wprowadzono ciąg znaków „abcdefghijk”. Program powinien zwrócić na ekran następujący rezultat:

0x08 graphic

Opracowany algorytm działał następująco:

Działanie pętli

Ustalono, że najlepszą pętlą do wykorzystania w podanym algorytmie będzie pętla for. Ogólną strukturę i formę zapisu pętli podejrzano ze strony http://rudy.mif.pg.gda.pl/~bogdro/linux/index.php i wykorzystano ją w działaniu programu. Pętla wyglądała następująco:

0x08 graphic

Niestety na zajęciach laboratoryjnych nie udało się przekonwertować podanej pętli na pętlę działającą pod kompilatorem laboratoryjnym. Pętla oddana na zajęciach była błędna i wyglądała następująco:

0x08 graphic

Przy dłuższej analizie pętli dla danego kompilatora, ustalono prawdziwą strukturę pętli for, która przykładowo powinna wyglądać następująco:

0x08 graphic

Główny program

Główny program pozostał praktycznie bez zmian w porównaniu do tego, oddawanego na poprzednich laboratoriach. Należało jedynie uwzględnić bufor i trzy dodatkowe zmienne. Po przeróbkach program powinien wyglądać następująco:

0x08 graphic

Zawartość eax przenosimy do ebx, gdyż w przyszłości akumulator będzie nam potrzebny przy dzieleniu. Eax zatrzymuje się na następnym wolnym bicie, stąd zmniejszenie ebx o jeden, by „wskoczyć” na zapełniony ciąg znaków. Po tym fragmencie powinny pojawić się pętle.

Pętle w programie

0x08 graphic

Skoki do add1,2 i 3 służą umiejscowieniu znaku w odpowiedniej zmiennej tekstowej. Znak jest mały dlatego można posłużyć się końcówką „b” w komendach.

Add1 służy umiejscowieniu znaku, jeśli występuje jako trzeci lub jako wielokrotność trzeciego. Przypisujemy zatem do zmiennej txt3.

0x08 graphic

Komenda zapisu/odczytu w buforze lub zmiennej tekstowej wygląda następująco:

Bufor (a, b, c), gdzie:

a - miejsce startu w tablicy

b - ile razy chcemy przesunąć się

c - stopień skoku, ile klastrów zajmuje skok

Deklaracje add2 i add3 wyglądają podobnie:

0x08 graphic

0x08 graphic

Pętle w obecnym stanie zawsze zatrzymają się po wykonaniu jednego obiegu. Potrzeba nam jeszcze pętli, która będzie nas przenosić z powrotem do głównego ciała programu. Coś na kształt pętli if.

0x08 graphic

Wypisanie programu na ekran

Ostatnim krokiem, jest wypisanie zmiennych tekstowych na ekran. Wykonano zwykłą, znaną procedurą SYSWRITE.

0x08 graphic

Wnioski

Mimo, iż na zajęciach nie udało się stworzyć działającej pętli z powodu braku odpowiednich do tego materiałów i pomocy naukowych, po dokładniejszym zapoznaniu się z problemem, pętle nie przedstawiały większych problemów. Umownie pominięto schemat kompilacji i tworzenia pliku Makefile, przyjmując to za wiadome.

Strona 1 z 7

mov %ecx, 1

petla_for:

cmp %ecx, 10

jae koniec_petli

add %eax, %ecx

add %ecx, 3

jmp petla_for

koniec_petli:

Mov ecx, 1 ; ECX to zmienna I. i=1

petla_for:

cmp ecx, 10

jae koniec_petli ; wychodzimy, gdy i >= 10

add eax, ecx ; EAX to zmienna J. j=j+i

add ecx, 1 ; i=i+1

jmp short petla_for

koniec_petli:

a d g i

b e h j

c f i k

SYSEXIT = 1

SYSREAD = 3

SYSWRITE = 4

STDOUT = 1

STDIN = 0

EXIT_SUCCESS = 0

.align 32

.data

msg_hello: .ascii "Podaj imie\n"

msg_hello_len = . - msg_hello

msg_text: .ascii " "

mas_text_len = . - msg_text

msg_hel: .ascii " "

msg_hel_len = . - msg_hel

.global _start

_start:

mov $SYSWRITE, %eax

mov $STDOUT, %ebx

mov $msg_hello, %ecx

mov $msg_hello_len, %edx

int $0x80

mov $SYSREAD, %eax

mov $STDIN, %ebx

mov $msg_hel, %ecx

mov $msg_hel_len, %edx

int $0x80

mov $SYSWRITE, %eax

mov $STDOUT, %ebx

mov $msg_hel, %ecx

mov $msg_hel_len, %edx

int $0x80

mov $SYSEXIT, %eax

mov $EXIT_SUCCESS, %ebx

int $0x80

p3:

decl %ebx

movl %ebx, %eax

cltd

movl $3, %ecx

div %ecx

popl %ecx

jmp koniec

SYSEXIT = 1

SYSREAD = 3

SYSWRITE = 4

STDOUT = 1

STDIN = 0

EXIT_SUCCESS = 0

bufor_len=200 //dlugosc bufora

txt_len=(200/3)+2 //dlugosc zmiennych txt

.lcomm bufor, bufor_len

.lcomm txt1, txt_len

.lcomm txt2, txt_len

.lcomm txt3, txt_len

.align 32

.data

.global _start

_start:

mov $SYSREAD, %eax //funkcja czytania z

mov $STDIN, %ebx //klawiatury

mov $bufor, %ecx

mov $bufor_len, %edx

int $0x80

movl $txt1, %edi //przypisanie txt do

movl $txt2, %esi //odpowiednich rejestrow

movl $txt3, %ecx

movl %eax, %ebx //przepisanie eax do ebx

decl %ebx //zmniejszenie ebx o 1

p3: //początek petli

decl %ebx //zmniejszenie ebx o jeden na potrzębę pętli

movl %ebx, %eax //przepisanie ebx do eax

cltd //rozłożenie eax na eax i edx

movl $3, %ecx //przeniesienie 3 do ecx przez które będziemy dzielic

div %ecx //dzielenie eax przez ecx -> edx - reszta

cmpl $0, %edx //porównanie reszty do zera

je add1 //jeśli rowne skocz do add1

cmpl $1, %edx //porównanie reszty do 1

je add2 //jeśli rowne skocz do add2

jmp add3 //skok bezwarunkowy do add3

jmp koniec //koniec petli

add1:

movb bufor(0, %ebx, 1), %al //zapis znaku z bufora do akumulatora

movb %al, txt3(0, %edi, 1) //zapis z akumulatora do txt3

incl %edi //zwiekszenie edi o 1

jmp koniec //skok bezwarunkowy

add2:

movb bufor(0, %ebx, 1), %al //zapis znaku z bufora do akumulatora

movb %al, txt1(0, %edi, 1) //zapis z akumulatora do txt1

incl %edi //zwiekszenie edi o 1

jmp koniec //skok bezwarunkowy

add3:

movb bufor(0, %ebx, 1), %al //zapis znaku z bufora do akumulatora

movb %al, txt2(0, %edi, 1) //zapis z akumulatora do txt2

incl %edi //zwiekszenie edi o 1

jmp koniec //skok bezwarunkowy

cmpl $0, %ebx //porównanie ebx do 0

ja p3 //jeśli ebx>0 skacz do p3

mov $SYSWRITE, %eax //wypisanie txt1

mov $STDOUT, %ebx

mov $txt1, %ecx

mov $txt1_len, %edx

int $0x80

mov $SYSWRITE, %eax //wypisanie txt2

mov $STDOUT, %ebx

mov $txt2, %ecx

mov $txt2_len, %edx

int $0x80

mov $SYSWRITE, %eax //wypisanie txt3

mov $STDOUT, %ebx

mov $txt3, %ecx

mov $txt3_len, %edx

int $0x80

mov $SYSEXIT, %eax //zakończenie programu

mov $EXIT_SUCCESS, %ebx

int $0x80



Wyszukiwarka