@ Jan Potocki 2020

@ Definicje numerow funkcji systemowych i ich parametrow
SYSEXIT = 1
SYSREAD = 3
SYSWRITE = 4
STDIN = 0
STDOUT = 1

@ Stale okreslajace rozmiar przetwarzanych danych
num_length = 256
@ ...tego nie ruszac - inaczej stanie sie "cud nad klawiatura" :-D
word_length = 4
buf_length = num_length * 2
num_words = num_length / word_length
buf_words = buf_length / word_length

.global main

@ Segment niezainicjalizowanych danych
.bss
num1: .space num_length
num2: .space num_length
result: .space buf_length

@ Segment kodu
.text
main:

@ Glowna petla
loop:
mov r7, #SYSREAD            @ Wczytanie danych ze standardowego wejscia
mov r0, #STDIN              @ ...funkcja systemowa read
ldr r1, =num1
mov r2, #buf_length
swi 0x0

@ UWAGA
@ Tutaj wczytane zostana od razu obie liczby
@ num1 i num2 sa w pamieci bezposrednio po sobie...
@ ...i zostala przekazana do funkcji read dlugosc calego bloku

cmp r0, #buf_length         @ r0 - liczba wczytanych bajtow
blt end                     @ Jezeli nie ma 512, to dane sie skonczyly

ldr r8, =num1               @ r8 - adres pierwszej liczby
ldr r9, =num2               @ r9 - adres drugiej liczby
ldr r10, =result            @ r10 - adres bufora na wynik

eor r0, r0, r0              @ r0 - wartosc zero (do zapisu w pamieci)

eor r4, r4, r4              @ r4 - indeks petli zerujacej

@ Petla zerujaca bufor na wynik
zero:
str r0, [r10, r4, lsl#2]
add r4, r4, #1
cmp r4, #buf_words
blt zero

eor r4, r4, r4              @ r0 - indeks pierwszej petli

@ Mnozenie - petla zewnetrzna
loop1:
eor r2, r2, r2              @ r2 - miejsce na starsza czesc wyniku

@ Flagi przeniesienia (potrzebne sa dwie i tego sie nie uprosci)
eor r11, r11, r11           @ r11 - dla biezacego mnozenia (rejestry)
eor r12, r12, r12           @ r12 - dla koncowego wyniku (w pamieci)

eor r5, r5, r5              @ r5 - indeks drugiej petli

@ Mnozenie - petla wewnetrzna
loop2:
ldr r0, [r8, r4, lsl#2]
ldr r3, [r9, r5, lsl#2]
umull r0, r1, r0, r3

@ Dodanie starszej czesci wyniku z poprzedniej iteracji
msr apsr_nzcvq, r11         @ Ladowanie flag z r11
adcs r0, r0, r2             @ Dodawanie z przeniesieniem i ustawieniem flag
mrs r11, apsr               @ Zapis rejestru apsr (calego) w r11

mov r2, r1                  @ Przechowanie starszej czesci wyniku w r2

add r6, r4, r5              @ r6 - indeks wyniku (suma indeksow obu petli)

msr apsr_nzcvq, r12         @ Ladowanie flag z r12
ldr r1, [r10, r6, lsl#2]
adcs r1, r0, r1             @ Dodawanie z przeniesieniem i ustawieniem flag
str r1, [r10, r6, lsl#2]
mrs r12, apsr               @ Zapis rejestru apsr (calego) w r12

add r5, r5, #1
cmp r5, #num_words
blt loop2                   @ Koniec wewnetrznej petli

@ Tutaj musimy sie jeszcze zajac najstarsza czescia wyniku
@ (z ostatniej iteracji petli wewnetrznej)
add r6, r6, #1

msr apsr_nzcvq, r11         @ Ladowanie flag z r11
adc r2, r2, #0              @ Dodawanie z przeniesieniem bez ustawiania flag

msr apsr_nzcvq, r12         @ Ladowanie flag z r12
ldr r1, [r10, r6, lsl#2]
adc r1, r1, r2              @ Dodawanie z przeniesieniem bez ustawiania flag
str r1, [r10, r6, lsl#2]

add r4, r4, #1
cmp r4, #num_words
blt loop1                   @ Koniec zewnetrznej petli

mov r7, #SYSWRITE           @ Wypisanie wyniku na standardowe wyjscie
mov r0, #STDOUT             @ ...funkcja systemowa write
ldr r1, =result
mov r2, #buf_length
swi 0x0

b loop                      @ Koniec glownej petli

end:
mov r7, #SYSEXIT            @ Funkcja systemowa exit...
mov r0, #0                  @ ...kod zakonczenia - 0
swi 0x0
