diff --git a/lab2-v3/Makefile b/lab2-v3/Makefile new file mode 100644 index 0000000..726fa41 --- /dev/null +++ b/lab2-v3/Makefile @@ -0,0 +1,7 @@ +all: mul + +mul: mul.s + gcc mul.s -o mul + +clean: + rm mul diff --git a/lab2-v3/README.md b/lab2-v3/README.md new file mode 100644 index 0000000..3713736 --- /dev/null +++ b/lab2-v3/README.md @@ -0,0 +1,17 @@ +Należy napisać program, który: +* Ze standardowego strumienia wejściowego odczyta (za pomocą funkcji systemowej _read_) bloki zawierające 512 bajtów każdy. Liczba bloków może być dowolna. Kombinacje bitów w bajtach mogą być dowolne. +* Każdy blok potraktowany zostanie jako zapisane po sobie dwie reprezentacje w kodzie naturalnym binarnym. Pierwszy odczytany bajt w bloku zawiera najmniej znaczący bit reprezentacji. Każda z reprezentacji zajmuje ciągłą połowę odczytanego bloku, czyli układ danych w bloku można opisać jako: +`A0 A1 A2 ... A255 B0 B1 B2 ... B255` +gdzie `Ai` i `Bi` oznaczają kolejne bajty (o indeksach _i_) reprezentacji pierwszej (A) i drugiej (B). +* Po odczytaniu bloku danych, na standardowe wyjście zostanie wypisana reprezentacja iloczynu liczb zapisanych reprezentacjami _A_ i _B_. Format reprezentacji wyjściowej będzie taki sam, jak wejściowych, ale o odpowiednio dopasowanej wielkości. + + +Przykładowe dane wejściowe i oczekiwane wyniki są dostępne pod adresem http://zak.iiar.pwr.wroc.pl/materials/architektura/laboratorium%20AK2/Dane/mul.tar.bz2 +Pliki z rozszerzeniem `.in` to dane wejściowe, pliki `*.out` to oczekiwane odpowiedzi. +Docelowo program ma działać dla danych z plików `mul_256.*`, ale dla ułatwienia Państwu pracy na początku realizacji zadania przygotowałem także pliki z reprezentacjami 4-bajtowymi (pliki `mul_4.*`). + +Podczas implementacji największe problemy może Państwu sprawić poprawna realizacja algorytmu mnożenia. +Przykładowe koncepcje należy sobie przypomnieć z materiałów z poprzedniego semestru, np. slajdy 38 i 39 pliku http://zak.iiar.pwr.wroc.pl/materials/Arytmetyka%20komputerow/architekura.pdf i podstawy z pliku http://zak.iiar.pwr.wroc.pl/materials/Arytmetyka%20komputerow/mnozenie.pdf +Oczywiście zadanie to można zrealizować na wiele sposobów, zmieniając zarówno rozmiar pojedynczych iloczynów częściowych, jak i kolejność ich kumulacji. +Można np. kumulację iloczynów częściowych przeprowadzać "wierszami", dodając poszczególne iloczyny częściowe "w poziomie", można także kumulować "kolumnami" sumując iloczyny "w pionie". Można także stosować różne rozwiązania pośrednie. +Niezależnie jednak od przyjętego sposobu, koniecznie proszę pamiętać o właściwej propagacji przeniesień. diff --git a/lab2-v3/mul.s b/lab2-v3/mul.s new file mode 100644 index 0000000..eef0d75 --- /dev/null +++ b/lab2-v3/mul.s @@ -0,0 +1,149 @@ +# Jan Potocki 2020 + +# Definicje numerow funkcji systemowych i ich parametrow +SYSEXIT64 = 60 +SYSREAD = 0 +SYSWRITE = 1 +STDIN = 0 +STDOUT = 1 + +# Stale okreslajace rozmiar przetwarzanych danych +num_length = 256 +# ...tego nie ruszac - inaczej stanie sie "cud nad klawiatura" :-D +word_length = 8 +buf_length = num_length * 2 +num_words = num_length / word_length +buf_words = buf_length / word_length + +.global main + +# Segment niezainicjalizowanych danych +.bss + +liczba1: .space num_length +liczba2: .space num_length +wynik: .space buf_length + +# Segment kodu +.text + +main: +# Glowna petla +petla: +mov $SYSREAD, %rax # Wczytanie danych ze standardowego wejscia +mov $STDIN, %rdi # ...funkcja systemowa read +mov $liczba1, %rsi +mov $buf_length, %rdx +syscall + +# UWAGA +# Tutaj wczytane zostana od razu obie liczby +# liczba1 i liczba2 sa w pamieci bezposrednio po sobie... +# ...i zostala przekazana do funkcji read dlugosc calego bloku + +cmp $buf_length, %rax # rax - liczba wczytanych bajtow +jl koniec # Jezeli nie ma 512, to dane sie skonczyly + +xor %rsi, %rsi # rsi - licznik petli zerujacej + +# Petla zerujaca bufor na wynik +wyzeruj: +movq $0, wynik(, %rsi, 8) +inc %rsi +cmp $buf_words, %rsi +jl wyzeruj + +xor %rsi, %rsi # rsi - licznik pierwszej petli + +# Mnozenie - petla zewnetrzna +petla1: +xor %rcx, %rcx # rcx - miejsce na starsza czesc wyniku + +# Flagi przeniesienia (potrzebne sa dwie i tego sie nie uprosci) +mov $0, %r8 # r8 - dla koncowego wyniku (w pamieci) +clc # RFLAGS - dla biezacego mnozenia (rejestry) +pushf # ...oczywiscie z backupem na stosie + +xor %rdi, %rdi # rdi - licznik drugiej petli + +# Mnozenie - petla wewnetrzna +petla2: +movq liczba1(, %rsi, 8), %rax +mulq liczba2(, %rdi, 8) + +mov %rdi, %r9 # r9 - indeks wyniku +add %rsi, %r9 # (suma indeksow obu petli) + +# Dodanie starszej czesci wyniku z poprzedniej iteracji +popf # Tutaj flagi mamy na stosie... +adc %rcx, %rax +pushf # ...wiec to jest proste + +# Przygotowanie flagi przeniesienia do sumowania wyniku (patent cz. I) +cmp $1, %r8 # Tego nie mamy na stosie... +je ustaw_cf1 # ...wiec musimy sprytnym sposobem ;-) + +clc # Przypadek bez przeniesienia +jmp dodaj_wynik + +ustaw_cf1: +stc # Przypadek z przeniesieniem + +# Dodawanie biezacego wyniku do pamieci +# (tam po wszystkich iteracjach bedzie wynik koncowy) +dodaj_wynik: +adcq %rax, wynik(, %r9, 8) + +# Zapisanie flagi przeniesienia do sumowania wyniku (patent cz. II) +jc zapisz_cf + +mov $0, %r8 # Jezeli przeniesienia nie bylo +jmp dalej + +zapisz_cf: +mov $1, %r8 # Jezeli przeniesienie bylo + +dalej: +mov %rdx, %rcx # Przechowanie starszej czesci wyniku w rcx + +inc %rdi +cmp $num_words, %rdi +jl petla2 # Koniec wewnetrznej petli + +# Tutaj musimy sie jeszcze zajac najstarsza czescia wyniku +# (z ostatniej iteracji petli wewnetrznej) +inc %r9 + +popf # Dodanie przeniesienia z sumowania rejestrow +adc $0, %rcx # ...jezeli jakies zostalo + +# Przygotowanie flagi przeniesienia do sumowania wyniku (patent cz. I) +cmp $1, %r8 +je ustaw_cf2 + +clc # Przypadek bez przeniesienia +jmp dodaj_najstarsze + +ustaw_cf2: +stc # Przypadek z przeniesieniem + +dodaj_najstarsze: +adcq %rcx, wynik(, %r9, 8) + +inc %rsi +cmp $num_words, %rsi +jl petla1 # Koniec zewnetrznej petli + +mov $SYSWRITE, %rax # Wypisanie wyniku na standardowe wyjscie +mov $STDOUT, %rdi # ...funkcja systemowa write +mov $wynik, %rsi +mov $buf_length, %rdx +syscall + +jmp petla # Koniec glownej petli + +# Wyjscie z programu +koniec: +mov $SYSEXIT64, %rax # Funkcja systemowa exit... +mov $0, %rdi # ...kod zakonczenia - 0 +syscall diff --git a/lab2-v3/mul.tar.bz2 b/lab2-v3/mul.tar.bz2 new file mode 100644 index 0000000..a80066e Binary files /dev/null and b/lab2-v3/mul.tar.bz2 differ