; Zadanie cislo 1
; 
; Text zadania: Napiste program, ktory nacita z klavesnice retazec znakov
;               (max. 100 znakov) a podla ponukaneho menu vykona jednu z moznosti:
;               a) vypise retazec znakov na obrazovku
;               b) vypise poradove cislo kde sa nachadza  prva medzera
;               c) spocita a vypise pocet cislic v retazci
;               d) zisti ci sa v retazci nachadza pouzivatelom zadany znak, ak ano
;               vypise vsetky iesta jeho vyskytu ak nie, vypise, ze sa v retazci 
;               dany znak nenachadza
;               e) vypise retazec v obratenom poradi 
;               f) ukonci vykonavanie programu.
;               Po vykonani zvolenej moznosti sa program vrati na vypis menu.
;               Nepouzivajte retazcove instrukcie!
;               Zdrojovy program musi byt PODROBNE OKOMENTOVANY!  
; 		Termin odovzdania: na cviceni do 6. tyzdna semestra
; 		Hodnotenie max. 8 bodov
; 



zas     segment stack 'stack'
        dw 50 dup(?)
zas 	ends

dat	segment
menu 	db        13,10
	db        '1. Nacitanie retazca',13,10
	db	  '2. Vypis retazca',13,10
        db        '3. Pocet cislic v retazci',13,10
        db        '4. Vyhladanie zadaneho znaku',13,10
        db 	  '5. Vypis retazca v obratenom poradi',13,10
	db        '6. Najdenie prvej medzery v retazci',13,10
        db  	  '7. Koniec programu',13,10,'> $'
newline db        13,10,'$'
vyzva1  db        13,10,'Zadajte retazec',13,10,'$'
oznam   db        13,10,'Zadali ste retazec:',13,10,'$'
cisla	db	  13,10,'Pocet cislic v retazci je: ','$'
znak    db        13,10,'Zadajte hladany znak: $'
no_znak db	  13,10,'Hladany znak sa nenachadza v retazci.$'
pozicia db 	  13,10,'Znak sa nachadza na nasledovnej pozicii: $'
prv_med db	  13,10,'Prva medzera je na pozicii cislo:','$'
opako   db 	  13,10,'Retazec v obratenom poradi: $'
temp 	db 	  100 dup(0)
pocet 	db 	  100
dat 	ends	

code    segment 
	assume cs:code, ss:zas, ds:dat

;-----------------------------------------
vypmenu proc                     ;procedura pre vypis menu
	mov ax,seg dat           
	mov ds,ax
	mov dx,offset menu       ;pomocou instrukcie int sa vypise menu
	mov ah,09h
	int 21h
	ret
	endp
;------------------------------------------

nacitret proc                  ;procedura pre nacitanie retazca
	xor cx,cx
	mov ax,seg dat
	mov ds,ax
	mov dx,offset vyzva1   ; vypis vyzvy pre zadanie retazca
	mov ah,09h
	int 21h
	mov bx,offset temp
uloz:   cmp al,13              ;kontrola ci bol stlaceny enter = koniec retazca
	jz nacit_end
	mov ah,1               ;nacitanie znaku z klavesnice sluzbou 01h
	int 21h
	mov [bx],al            ;ulozenie nacitaneho znaku do pola temp
	inc bx
	inc cx
	dec pocet              ;kontrola ci dlzka retazca nie je viac ako 100
	jnz uloz
nacit_end:	mov bx,offset temp
	inc cl
	add bx,cx
	mov [bx],36            ;ukoncenie nacitaneho retazca znakom $
	ret
	endp
	
;---------------------------------------
vypis_ret proc                    ;procedura pre vypis retazca
	
	mov ax,seg dat
	mov ds,ax        
	mov dx,offset oznam       ;vypis oznamu o vypisanie retazca
	mov ah,09h
	int 21h
	mov bx,offset temp
	mov dx,[bx]               ;presun prveho znaku z pola temp do registra dx
	mov ah,2h                 ;vypis znaku
	int 21h
	mov dx,offset temp        ;vypis celeho retazca
	mov ah,09h
	int 21h
	ret 
	endp

;--------------------------------------
poc_cislic proc                   ;procedura pre zistenie poctu cislic v retazci
	xor cx,cx                 ;vynulovanie registra cx
	mov ax,seg dat
	mov ds,ax
	mov bx,offset temp
znovu:	mov ax,[bx]               ;nacitanie znaku z pola do registra ax     
	inc bx
	cmp al,'$'                ;test na $
	jz kon                    ;ak znak = $ koniec  proc
	cmp al,'0'                ;kontrola ci je nacitany znak cislo
	jbe znovu
	cmp al,'9'
	jnb znovu
	inc cl                    ;ak ano cl sa zvacsi o jeden
	jmp znovu                 ;pokracovanie testovania az kym nenarazi na $ 
kon:	xor ax,ax
	mov dx,offset cisla       ;vypis o pocte cisel  
	mov ah,09h
	int 21h
	mov si,cx                 
	call vypis                ;pomocou proc vypis sa vypise pocet najdenych cisel
	ret
	endp

;---------------------------------------
medzera proc                      ;procedura pre zistenie pozicie prvej medzery
	xor cx,cx                 ;vynulovanie registra cx
	mov ax,seg dat
	mov ds,ax
	mov bx,offset temp
opak:   mov ax,[bx]               ;zapisanie znaku z pola do registra ax 
	inc bx
	inc cl
	cmp al,' '                ;kotrola ci znak je medzera
	jnz opak                  ;ak nie tak sa pokracuje v prehladavani 
	mov dx,offset prv_med     ;vypis pozicie prvej medzery 
	mov ah,09h
	int 21h
	mov si,cx                 
	call vypis                ;vypis cisla pozicie 
	ret
	endp
	
;--------------------------------------
vypis proc                        ;procedura pre vypis desiatkoveho cisla
	xor cx,cx                 ;vynulovanie registra cx
	mov dx,si      
s10:    cmp dx,10                 ; je dx >= 10 ?	
	jb s1
	sub dx,10                 ;bude v cykle odcitavat od dx 10 az dovtedy kym dx<10
	inc cl                    ;v cl je zapisany pocet desiatok
	jmp s10
s1:     mov bl,dl
	add bl,30h                ;pripocitanim 30h k cislu ziskame jeho ASCII kod
	add cl,30h
	mov ah,2                  ;funkcia pre vypis retazca  
        mov dl,cl
	int 21h                   ;vypis desiatky
	mov dl,bl              	  ;vypis jednotky
	int 21h
	ret
	endp

;---------------------------------------
find_char proc                    ;procedura pre vyhladanie zadaneho znaku 
	xor cx,cx                 ;vynulovanie registra cx
	mov ax,seg dat 
	mov ds,ax 
	mov dx,offset znak        ;vypis oznamu             
	mov ah,09h 
	int 21h 
	mov ah,1                  ;nacitanie hladaneho znaku 
	int 21h 
	mov dl,al                 ;ulozenie nacitaneho znaku do registra dl 
	mov bx,offset temp 
oko:    mov ax,[bx]               ;nacitanie znaku z retazca
	inc bx                    
	cmp al,'$'                ;kontrola konca retazca
	jz ok 	                  ;ak znak = $, tak skoci na ok  
	cmp al,dl                 ;porovnanie nacitaneho znaku s hladanym znakom
	jnz oko                   ;ak nie tak sa pokracuje v testovani 
	inc cx                    ;zistovanie poctu opakovani hladaneho znaku
	push bx                   ;ulozenie pozicie najdeneho znaku do zasobnika
	jmp oko                   ;pokracovanie v testovani 
ok: 	cmp cx,0                  ;kontrola ci bol najdeny hladany znak
	jz noch                   ;ak nie skok na noch 
	mov dx,offset pozicia     ;vypis pozicii hladaneho znaku 
	mov ah,09h 
	int 21h 
out: 	mov bx,offset temp        ;ulozenie adresy zac. pola do bx 
	pop ax                    ;vytiahnutie pozicie najdeneho znaku zo zasobnika
	sub ax,bx                 ;odcitanim sa ziska poradove cislo pozicie najdeneho znaku 
	mov si,ax 
	push cx                   ;ulozenie cx do stacku
	mov dx,offset newline     ;odriadkovanie 
	mov ah,09h
	int 21h 
	call vypis                ;vypis pozicie najdeneho znaku 
	pop cx                    ;obnovenie hodnoty cx - pocet opakovani znaku 
	dec cx                    ;zmensenie cx o 1
	jnz out                   ;kym cx>1 skok na out:
	jmp dost                  ;skok na ukoncenie vyhladavania
noch: 	mov dx,offset no_znak     ;vypis oznameni o nenajdeni ziadneho znaku 
	mov ah,09h 
	int 21h 
dost:   ret 
	endp

;---------------------------------------
op_vyp proc                       ;vypis retazca naopak
	xor cx,cx
	mov ax,seg dat
	mov ds,ax
	mov bx,offset temp
furt:	mov ax,[bx]               ;zvacsujem bx do vtedy kym nenarazi na $ 
	inc bx
	inc cx                    ;ziskanie poctu znakov
	cmp al,'$'                ;kontrola na $ 
	jnz furt
	push cx                   ;ulozenie cx do zasobnika
	push bx                   ;ulozenie bx do zasobnika           
	mov dx,offset opako       ;vypis retazca naopak 
	mov ah,09h
	int 21h
	mov dx,offset newline     ;odriadkovanie   
	mov ah,09h
	int 21h
	pop bx                    ;obnovenie bx
	pop cx                    ;obnovenie cx
	dec bx                    ;zmensenie bx o 1
ooo:	mov dx,[bx]               ;ulozenie znaku z pola do registra dx 
	dec bx                    ;zmensenie bx o 1
	push bx                   ;uchovanie bx v zasobniku
	mov ah,02h                ;vypis znaku ulozeneho v dx 
	int 21h
	pop bx                    ;obnovenie bx
	dec cx                    ;zmensenie poctu prvkov 
	jnz ooo                   ;opakuj az kym cx != 0
	mov dx,offset newline     ;odriadkovanie 
	mov ah,09h
	int 21h
	ret
	endp
;---------------------------------------
start:
	call vypmenu               ;vypis menu
	mov ah,8                   ;nacitanie volby menu 
	int 21h
m1:	cmp al,49                  ;zvolil si volbu cislo 1 ?
	jnz m2
	call nacitret              ;volanie podprogramu pre nacitanie retazca
	jmp start
m2:	cmp al,50                  ;zvolil si volbu cislo 2 ?
	jnz m3
	call vypis_ret             ;volanie podprogramu pre vypis retazca 
	jmp start
m3:	cmp al,51                  ;zvolil si volbu cislo 3 ?
	jnz m4
	call poc_cislic            ;volanie podprogramu pre zistenie poctu cislic
	jmp start
m4:	cmp al,52                  ;zvolil si volbu cislo 4 ?
	jnz m5
	call find_char             ;volanie podprogramu pre vyhladanie znaku
	jmp start
m5:	cmp al,53                  ;zvolil si volbu cislo 5 ?
	jnz m6
	call op_vyp                ;volanie podprogramu pre vypisanie retazca odzadu
	jmp start
m6:	cmp al,54                  ;zvolil si volbu cislo 6 ?
	jnz m7
	call medzera               ;volanie podprogramu pre vyhladanie prvej medzery
	jmp start
m7:     cmp al,55                  ;zvolil si volbu cislo 7 ?	
	jmp koniec                 ;ukoncenie programu
koniec:	mov ah,4ch
	int 21h
code 	ends
end 	start


; Zhodnotenie:
; Program je plne funkcny. Program bol vytvoreny v programovacom prostredi
; Turbo Assembler ver. 2.02 resp. v Turbo Debugeri ver. 2.02. 
; Vzhladom na vstupne udaje je program citlivy na volbu z menu.
; Ak je totiz zadana nejaka ina volba ako sa predpoklada tak program 
; prestane pracovat. Program pri svojej praci pouziva DOSovske sluzby
; 01h, 02h, 08h, 09h a pre prerusenie int 21h.