Wydanie R2020.05.1

This commit is contained in:
Jan Potocki
2020-05-09 22:17:22 +02:00
parent 8f4d0e843f
commit 0ba84bef75
11 changed files with 339 additions and 0 deletions
+13
View File
@@ -0,0 +1,13 @@
all: fibb_32 fibb_64 second
fibb_32: fibb_c.c fibb32.s timestamp32.s
gcc -m32 fibb32.s timestamp32.s fibb_c.c -o fibb_32
fibb_64: fibb_c.c fibb64.s timestamp64.s
gcc -no-pie fibb64.s timestamp64.s fibb_c.c -o fibb_64
second: second.c timestamp32.s
gcc -m32 timestamp32.s second.c -o second
clean:
rm fibb_32 fibb_64 second
+43
View File
@@ -0,0 +1,43 @@
# Jan Potocki 2020
.global fibb
# Segment kodu
.text
fibb:
push %ebp
mov %esp, %ebp
push %ebx
cmpl $0, 8(%ebp)
je zero
cmpl $1, 8(%ebp)
je jeden
movl 8(%ebp), %edx
dec %edx
push %edx
call fibb
pop %edx
mov %eax, %ebx
dec %edx
push %edx
call fibb
add $4, %esp
add %ebx, %eax
jmp wyjscie
zero:
mov $0, %eax
jmp wyjscie
jeden:
mov $1, %eax
wyjscie:
pop %ebx
pop %ebp
ret
+40
View File
@@ -0,0 +1,40 @@
# Jan Potocki 2020
.global fibb
# Segment kodu
.text
fibb:
push %rbp
mov %rsp, %rbp
push %rbx
cmp $0, %rdi
je zero
cmp $1, %rdi
je jeden
dec %rdi
push %rdi
call fibb
pop %rdi
mov %rax, %rbx
dec %rdi
call fibb
add %rbx, %rax
jmp wyjscie
zero:
mov $0, %rax
jmp wyjscie
jeden:
mov $1, %rax
wyjscie:
pop %rbx
pop %rbp
ret
+21
View File
@@ -0,0 +1,21 @@
#include <stdio.h>
unsigned long fibb(unsigned long n);
unsigned long long timestamp();
int main()
{
unsigned long term, result;
unsigned long long tstamp1, tstamp2;
scanf("%lu", &term);
tstamp1 = timestamp();
result = fibb(term);
tstamp2 = timestamp();
printf("%lu\n", result);
printf("Cycles: %llu\n", tstamp2-tstamp1);
return 0;
}
+20
View File
@@ -0,0 +1,20 @@
#include <stdio.h>
#include <unistd.h>
// Jan Potocki 2020
unsigned long long timestamp();
int main()
{
unsigned long long tstamp1, tstamp2;
tstamp1 = timestamp();
sleep(1);
tstamp2 = timestamp();
printf("Cycles: %llu\n", tstamp2 - tstamp1);
return 0;
}
+13
View File
@@ -0,0 +1,13 @@
# Jan Potocki 2020
.global timestamp
# Segment kodu
.text
timestamp:
xor %eax, %eax
cpuid
rdtsc
ret
+16
View File
@@ -0,0 +1,16 @@
# Jan Potocki 2020
.global timestamp
# Segment kodu
.text
timestamp:
xor %rax, %rax
cpuid
rdtsc
shl $32, %rdx
or %rdx, %rax
ret
+7
View File
@@ -0,0 +1,7 @@
all: mul
mul: mul.s
gcc mul.s -o mul
clean:
rm mul
+17
View File
@@ -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ń.
+149
View File
@@ -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
Binary file not shown.