;program Zadanie c.1
;autor: Ludovit Fulop
;kruzok: b9

zas	segment	stack 'stack'		; definicia zasobnika
	dw 64 dup(?)
zas	ends

data	segment				; definicia datoveho segmentu
vstup 	db	101			; vstupny retazec - max velkost
pocet	db	0			; pocet znakov v nom
	db	101 dup(?)		; samotny  retazec
info1	db	10,13,'Zadaj retazec (max 100 znakov):',10,13,'$'  
info2	db	10,13,'Zadany retazec:',10,13,'$'	; user-friendly 
info3	db 	10,13,'Poloha prvej medzery:',10,13,'$'	; retazce, hovoria sami
info31	db	10,13,'Medzera sa v retazci nevyskytuje',10,13,'$'	;za seba
info4	db	10,13,'Pocet cislic v retazci:',10,13,'$'
info41	db	10,13,'V retazci sa nevyskytuju ziadne cislice',10,13,'$'
info5	db	10,13,'Zadaj hladany znak: $'
info51	db	10,13,'Vyskyt daneho znaku:',10,13,'$'
info52	db	10,13,'Dany znak sa v retazci nenachadza',10,13,'$'
info6	db	10,13,'Zrkadlovy vypis retazca:',10,13,'$'
menu	db	'1/Vypis retazca',10,13			;polozky menu
	db	'2/Najst polohu prvej medzery',10,13
	db	'3/Zistit pocet cislic',10,13
	db	'4/Hladat znak v retazci',10,13
	db	'5/Vypisat odzadu',10,13
	db	'6/Koniec',10,13,'$'
znk	db 0		; hladany znak 
jeznak	db 0		; indikuje, co si dany znak vretazci nachadza
data ends

code segment				; zaciatok kodoveho segmentu
assume cs:code, ds:data, ss:zas		; priradenie segmentof

pisret  proc				; procedura pre vypis retazca
	mov ah,09h			; dos fn 09 - vypis retazca
	int 21h				; zavolanie sluzby dosu
	ret	; tato funkcia ocakave pripravenost retazca na ds:dx
	endp

cakaj 	proc				; procedura na cakanie na klavesu
	mov ah,08h			; dos fn 08-vstup znaku bez echa
	int 21h				; zavolanie sluzby
	ret
	endp

nacitaj proc				; procedura na nacitanie retazca
	mov ax,seg info1		; vypisanie informacie pre usera
	mov ds,ax			; segmentova cast adresy retazca		
	mov dx, offset info1		; offsetova -||-
	call pisret			; zavolanie procedury pre vypis
	mov ax,seg vstup		
	mov ds,ax			; adresa vstupnehoo retazca
	mov dx, offset vstup
	mov ah,0ah			; dos fn 0a- nacitanie retazca
	int 21h				; zavolanie sluzby dosu

	mov al,[vstup+1]		; pridanie ukoncovacich znakov
	mov bx,offset vstup+2		
	xor ah,ah
	add bx,ax
	mov byte ptr [bx],13
	mov byte ptr [bx+1],10
	mov byte ptr [bx+2],'$'
	mov ah,2			; prejde na dalsi riadok
	mov dl,10
	int 21h
	mov dl,13
	int 21h
	ret
	endp

vypisret proc					; procedura na vypis retazca
	mov ax, seg info2			; ulozenie segmentu a 
	mov ds,ax				; offsetu do cs:dx
	mov dx, offset info2			; a vypianie informacie pre
	call pisret				; uzivatela
	mov ah,2
	mov bx, offset vstup+2
	xor cx,cx
	mov cl, [bx-1]
	cyklus:mov dl, [bx]			; vypisovanie retazca po
	inc bx					; po znakoch, aby sa osetril
	int 21h					; $ v retazci
	loop cyklus
	call cakaj				; cakanie na klavesu
	ret
	endp

piscislo proc			; proc. na prevod cisla do znakov a vypis
	push ax			; ulozenie registorv do zasobnika
	push bx			
	push dx
	mov ah,2		; dos fn 02- vypis znaku
	xor bx,bx
	mov bl,al		; ulozenie cisla do bl
	cmp bx,100		; je vacsie ako 100?
	jl des			; ak je mensie ako 100, chod na desiatky
	sub bx,100		; inak odictaj 100
	mov dl,31h		; a vypis 100
	int 21h			; o desiatky a jednotky sa nemusim starat,
	mov dl,30h		; lebo max dlzka reatzca je 100
	int 21h
	jmp jedn 
	des: cmp bx,10		; je cislo vacsie ako 10?
	jl jedn			; ak je mensie ako 10, chod na jednotky
	mov dl,0		; pocitadlo desiatok
	cykl:
	inc dl			; zvys desiatkovy rad o 1
	sub bx,10		; odpocitaj 10
	jnc cykl		; je zvysok <0?
	dec dl			; ak ano, zniz des. rad (kuoli jednotkovemu)
	add dl, 30h		; vyrataj ascii kod cisla
	int 21h			
	add bx,10		; navrat z podtecenia...dostaneme jednotky
	jedn: add bx, 30h	; vyrata ascii kod cisla
	mov dl, bl		
	int 21h			; a vypise ho
	pop dx			; vrati povodne hodnoty registrof
	pop bx
	pop ax
	ret
piscislo endp

medzera proc				;proc. pre zistenie prvej medzery
       	mov bx, offset vstup+2		; bx <- offset retazca
	xor cx,cx
	mov cl, [bx-1]			; pocet znakov 
	mov dx,-1			; poloha medzery
	cmp cx,0			; je retazec prazdny?
	jz nospace			; ak hej, nema medzery :)
	cyk3: mov al,[bx]		; ulozenie 1 znaku do al
	inc bx				; zvysenie offsetu znaku
	inc dx				; zvysenie pocitadla polohy
	cmp al, 32			; porovnanie znaku s medzerou
	loopnz cyk3			; opakovanie kym cx<>0 alebo medzera
	cmp al, 32			; ak to nie je medzera
	jnz nospace			; skok na vypis infa
	mov ax, seg info3		; informacia pre uzivatela
	mov ds, ax
        push dx
	mov dx, offset info3
	call pisret
	pop dx
	inc dl
	mov al,dl			; v al je poloha
	call piscislo			; vypisanie cisla v al	
	jmp kon3	
	nospace: 			; vypis informacie o nenajdeny
	mov ax, seg info31		; medzery
	mov ds, ax
	mov dx, offset info31
	call pisret
	kon3:call cakaj
	ret
	endp	

cislice proc				; procedura na zistenie poctu cislic
	mov bx, offset vstup+2		; offset zadaneho retazca
	xor cx,cx
	mov cl, [bx-1]			; jeho dlzka
	mov dx,0			; pocitadlo cislic
	cmp cx,0			; je retazec prazdny?
	je nonums			; ak ano vypis info
	cyk4: mov al, [bx]		; uloz do al znak
	inc bx				; zvys offset znaku
	cmp al,48			; zistovanie ci je dany znak
	jl cont				; cislica
	cmp al,48+9
	jg cont				; ak ano...
	inc dx				; ..zvysi pocitadlo o 1
	cont:loopnz cyk4		; opakuj, kym cx<>0
	cmp dx,0			; ak je pocet cislic 0,
	je nonums			; vypis info 
	mov cx, dx			; inak ...
	mov ax, seg info4
	mov ds, ax
	mov dx, offset info4
	call pisret
	mov al,cl
	call piscislo			; ...vypis cislo
	jmp kon4
	nonums:				; vypis infa pre uzivatela
	mov ax, seg info41		; pocet cislic je nulovy
	mov ds,ax
	mov dx, offset info41
	call pisret
	kon4: call cakaj		; cakanie na klavesu
	ret
	endp
	
znak	proc				; procedura pre hladanie znaku
	mov ax,seg info5		; vypis " zadaj znak..."
	mov ds, ax
	mov dx, offset info5
	call pisret
	mov ah,1			; dos fn 01 - vstup znaku s echom
	int 21h	
	mov znk,al			; ulozenie znaku do ZNK
	mov ax, seg info51		; vypis " vyskyt znaku..."
	mov ds, ax
	mov dx, offset info51
	call pisret
	mov bx, offset vstup+2		; bx<- offset prveho znaku
	xor cx, cx
	mov cl, [bx-1]			; dlzka retazca
	mov dx,0			; poloha
	cmp cx, 0
	je nochar			; koniec ak retazec je prazdny
	cyk5: mov al, [bx]		; al <- znak
	inc bx				; zvysenie offsetu znaku
	inc dh				; zvysenie akt.polohy
	cmp al,znk			; je al-znk?
	jne pokr			; ak nie, preskoc toto :
	mov jeznak,1			; nastaenie priznaku
	mov al,dh
	call piscislo			; vypis aktualnej pozicie
	mov ah,2			; spravi medzeru medzi cislami
	mov dl,' '			
	int 21h
	pokr:loopnz cyk5		; opakuj od nacitania znaku
	cmp jeznak,0			; ak nebol najdeny znak, vypis info
	jne kon5			; inak chod na koniec
	nochar:
	mov ax, seg info52
	mov ds, ax
	mov dx, offset info52
	call pisret
	kon5: call cakaj		; cakanie na klavesu
	ret
	endp

odzadu	proc				; vypis retazca odzadu
	mov ax, seg info6		; vypis " vypis retazca odzadu..."
	mov ds, ax
	mov dx, offset info6
	call pisret
	mov bx, offset vstup+2		; offset prveho pismena
	xor cx,cx
	mov cl, [bx-1]			; pocet pismen
	add bx, cx			; bx<- offset posledneho pismena
	dec bx				; zniz bx (inak by ukazoval o 1 
	mov ah,2			; pismeno dalej
	cyk6:
	mov dl, [bx]			; dl <- pismeno na [bx]
	int 21h				; vypis pismena
	dec bx				; znizenie offsetu
	loopnz cyk6			; kym cx<>0, opakuj od nacitania
	call cakaj			; znaku
	ret
	endp

koniec proc				; ukoncenie programu
	mov ah,4ch			; dos fn 4ch - ukonci program
	int 21h
	ret
	endp

pismenu	proc				; procedura na vypisanie menu
	cyk1:mov ax,3			; vycistenie obrazovky
	int 10h
	mov ax, seg menu		; segmentova cast menu
	mov ds,ax
	mov dx, offset menu		; offsetova cast menu
	call pisret			; vypis menu
	call cakaj			; cakanie na volbu
	cmp al,'1'			; je to 1 
 	 jne m2				; ak nie, testuj dalej
 	 call vypisret			; ak ano, zavolaj prisl. proced.
	 jmp cyk1			; znovu menu
	m2: cmp al,'2'			; je to 2
	 jne m3
	 call medzera			; dtto
 	 jmp cyk1
	m3: cmp al,'3'			; je to 3
	 jne m4
	 call cislice			; dtto
	 jmp cyk1
	m4: cmp al,'4'			; je to 4
	 jne m5
	 call znak			; dtto
	 jmp cyk1
	m5: cmp al,'5'			; je to 5
	 jne m6
 	 call odzadu			; dtto
	 jmp cyk1
	m6: cmp al,'6'			; je to 6
	jne cyk1			; ak nebola stlacena 6, znovu menu
	ret				; inak chod dalej=> skonci :)
	endp

start:	call nacitaj			; nacitanie vsstup. retazca
	call pismenu			; vypis menu a praca s nim
	call koniec			; ukoncenie programu
code ends			; koniec codoveho segmentu
end start		