150 lines
3.9 KiB
ArmAsm
150 lines
3.9 KiB
ArmAsm
# 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
|