#################################################################
#
# Laboratorium 3. 
# Implementacja switch-case-break, przekazanie argumentow z linii komend,
# wywolanie funkcji jezyka C.
#
# Program ma wykonac wybrana operacje logiczna (ew. funkcje arytmetyczna),
# a nastepnie wyswietlic jej nazwe, dane wejsciowe i wynik operacji.
#
# Argumenty do programu nalezy przekazac jako parametry z linii komend:
#
# ./swcs2 arg1 arg2 nr_operacji_logicznej

.globl	main

#################################################################
#
# Alokacja pamieci - zmienne statyczne z nadana wartoscia poczatkowa.

.data

str_and:	.asciz	"%u AND %u = %u\n"
str_or:		.asciz	"%u OR %u = %u\n"
str_xor:	.asciz	"%u XOR %u = %u\n"
str_gcd:	.asciz	"GCD(%u , %u) = %u\n"

str_def:	.asciz	"DEFAULT\n"

arg_1:		.long	0
arg_2:		.long	0
result:		.long	0
case_no:	.long	0


# --- 2b ---
# Uzupelnic tablice adresow poszczegolnych sekcji switcha,
# numery przypadkow podane zostana przez prowadzacego.

jump_table: # ...


#################################################################
#
# Program glowny.

.text

main:

# Wyrownanie wierzcholka stosu do granicy 16 bajtow (przesun o 8 bajtow w dol).

sub	$8 , %rsp

# --- 1a - Przekazywanie parametrow z linii komend.
#
# Sprawdz, czy z linii komend przekazano trzy (cztery!) parametry,
# jesli nie - wyjdz (opcjonalnie zwracajac -1).

# ...

convert_argv:

# --- 1b --- Uzupelnic :
# konwertuj przekazane parametry (argv) z ciagu tekstowego na liczbe calkowita, np.

# Konwersja pierwszego parametru na liczbe:

mov	8(%rsi) , %rdi
call	atoi
mov	%eax , arg_1

# W podobny sposob dopisz konwersje dwoch kolejnych liczb:

# ...

# --- 2a --- Uzupelnic switch - case.
# Sprawdz, czy podany nr przypadku miesci sie w stablicowanym zakresie:

# ...

# Skok posredni: do adresu odczytanego z tablicy (czyli do odpowiedniego przypadku switcha):

# ...

# W kazdym z przypadkow (oprocz default) wykonaj odpowiednia operacje 
# logiczna (arytmetyczna) oraz przekaz niezbedne argumenty do funkcji printf.
# Mozna zoptymalizowac.

c_and:
mov	arg_1 , %esi
mov	arg_2 , %edx
mov	%edx , %ecx
and	%esi , %ecx
mov	$str_and , %rdi
jmp	brk

c_or:
mov	arg_1 , %esi
mov	arg_2 , %edx
mov	%edx , %ecx
or	%esi , %ecx
mov	$str_or , %rdi
jmp	brk

c_xor:
mov	arg_1 , %esi
mov	arg_2 , %edx
mov	%edx , %ecx
xor	%esi , %ecx
mov	$str_xor , %rdi
jmp	brk

c_gcd:

# --- 3a --- Uzupelnic:
# przekaz argumenty do funkcji GCD zgodnie z ABI,
# wywolaj funkcje GCD. Przekaz argumenty do f. printf.

#...

jmp	brk

c_def:
mov	$str_def , %rdi

brk:

# Czesc wspolna (dla wszystkich przypadkow):
# wywolaj funkcje printf z uprzednio umieszczonymi w odpowiednich rejestrach (wg ABI):
# adresem ciagu, argumentami i wynikiem operacji.

xor	%eax , %eax
call	printf

# Przesun wskaznik stosu o 8 bajtow w gore aby prawidlowo sciagnac adres powrotu z main.

add	$8 , %rsp

# Powrot z main, zwroc w %eax kod bledu.
xor	%eax , %eax
ret

#################################################################

# --- 3b --- Napisac funkcje GCD (Greatest Common Divisor) w asemblerze,
# argumenty i zwracana wartosc: w rejestrach zgodnych z ABI.

#unsigned int GCD(unsigned int a, unsigned int b) 
# { 
#   if (b==0) return a; 
#   else GCD(b, a % b); 
# } 

gcd:

# ...

ret

