; zadanie c.1
;---------------------------------------------------------------------------------------
; Program nacíta z klávesnice text (max.retazec 100 znakov) a podla menu vykoná tieto ulohy
; 1) vypise nacitany retazec
; 2) Hlada v retazci zadany znak a vypise jeho poziciu
; 3) Ukonci vykonavanie programu
;---------------------------------------------------------------------------------------
; Jozko Mrkvicka
; termin odovzdania: 28.10.2003
; 3.roc., 2003/2004


zasob	SEGMENT	STACK					; definicia zasobnikoveho segmentu (64B)
	DW	64 DUP(?)
zasob	ENDS


data	SEGMENT						; zaciatok dátoveho segmentu

vyzva1	DB	0AH, 0DH, 'Zadaj retazec: ', '$'	; Textove vyzvy pre uzivatela pouzite v programe

vyzva2	DB	0AH, 0DH, 'Zadaj znak: ', '$'

oznam_A	DB	0AH, 0DH, 'Zadany znak sa v retazci nachadza na pozicii ', '$'

oznam_N	DB	0AH, 0DH, 'Zadany znak sa v retazci nenachadza!', '$'

riadok	DB	0AH, 0DH, '$'

menu	DB	0AH, 0DH, 0AH, 0DH			; menu programu
	DB	'1) Vypis retazec', 0AH, 0DH
	DB	'2) Hladanie znaku v retazci', 0AH, 0DH
	DB	'3) Exit', 0AH, 0DH, 0AH, 0DH, '$'

							; miesto pre vstupny retazec:
vstup	DB	101					; maximálny pocet znakov v retazci (+1)
pocet	DB	0					; skutocny pocet znakov v retazci
retazec	DB	101 DUP('$')				; nacítany retezec

data	ENDS						; koniec dátoveho segmentu

;-----------------------------------------------------------------------------------------

CODE	SEGMENT						; zaciatok kódového segmentu
	ASSUME	CS:code, DS:data, SS:zasob		; definovanie segmentovych registrov

start:							; zaciatok
	MOV	AX, SEG data				; vyzva na zadanie retazca
	MOV	DS, AX
	MOV	DX, OFFSET vyzva1
	MOV	AH, 09H					; ziadost o vypísanie (volanie sluzby)
	INT	21H

	MOV	AX, SEG data				; nacítanie retazca
	MOV	DS, AX
	MOV	DX, OFFSET vstup
	MOV	AH, 0AH					; ziadost o vstup retazca  (volanie sluzby)
	INT	21H

zac:	MOV	AX, SEG data				; vypis MENU
	MOV	DS, AX
	MOV	DX, OFFSET menu
	MOV	AH, 09H					; ziadost o vypísanie (volanie sluzby)
	INT	21H

testuj:	MOV	AH, 8					; ziadost o znak z klávesnice (volanie sluzby)
	INT	21H

	CMP	AL, '1'					; bolo to "1"?
	JZ	vypis					; áno=>vypís retazec

	CMP	AL, '2'					; bolo to "2"?
	JZ	hladaj					; áno=>hladaj znak

	CMP	AL, '3'					; bolo to "3"?
	JZ	koniec					; áno=>ukoncit program

	JMP	testuj					; ak ani jedno, vrat sa nazat

koniec:	MOV	AX, 4C00H				; korektné ukoncenie programu
	INT	21H					; je umiestneny tuna, aby ho bolo mozne volat v kratkom skoku

vypis:	MOV	AX, SEG data				; "Vypisanie" enteru
	MOV	DS, AX
	MOV	DX, OFFSET riadok
	MOV	AH, 09H					; ziadost o vypísanie (volanie sluzby)
	INT	21H

	MOV	AX, SEG data				; priprava cyklu pre vypisanie retazca:
	MOV	DS, AX
	MOV	DX, [OFFSET pocet]			; pocet nacitanych znakov => CX (kvoli cyklu)
	MOV	SI, DX
	MOV	CL, [SI]
	MOV	CH, 0
	MOV	DX, OFFSET retazec			; nastavenie registrov na citanie znakov z pamate
	MOV	SI, DX

navrat:	MOV	DL, [SI]				; vypis RETAZCA (cyklus)
	INC	SI
	MOV	AH, 02H
	INT	21H					; samotny vypis (volanie sluzby)
	LOOP	navrat
	JMP	zac

hladaj:	MOV	AX, SEG DATA				; vyzva na zadanie znaku
	MOV	DS, AX
	MOV	DX, OFFSET vyzva2
	MOV	AH, 09					; ziadost o vypísanie (volanie sluzby)
	INT	21H
	MOV	AH, 01					; ziadost o znak z klávesnice (volanie sluzby)
	INT	21H

	PUSH	AX
	MOV	AX, SEG data				; priprava cyklu pre hladanie znaku
	MOV	DS, AX
	POP	AX
	MOV	DX, [OFFSET pocet]			; priprava registra CX (pocet znakov v retazci) pre cyklus
	MOV	SI, DX
	MOV	CL, [SI]
	MOV	CH, 0
	PUSH	CX					; odlozime pocet znakov retazca (budeme potrebovat neskor)
	MOV	DX, OFFSET retazec			; nastavenie registrov pre prehladavanie
	MOV	SI, DX

spat:	MOV	DL, [SI]				; prehladavanie retazca
	INC	SI
	CMP	DL, AL					; ak sa najde zhodny znak,
	JZ	ano					; skok na ANO
	LOOP	spat

	MOV	AX, SEG DATA				; oznam o neuspechu (nenasiel sa zhodny znak)
	MOV	DS, AX
	MOV	DX, OFFSET oznam_N
	MOV	AH, 09					; ziadost o vypísanie  (volanie sluzby)
	INT	21H
	
	POP	CX					; vytiahneme pocet znakov v retazci, aj ked tu tento
	JMP	zac					; udaj nie je potrebny a skok na MENU

ano:	MOV	AX, SEG DATA				; oznam o uspechu (znak bol najdeny)
	MOV	DS, AX
	MOV	DX, OFFSET oznam_A
	MOV	AH, 09					; ziadost o vypísanie  (volanie sluzby)
	INT	21H

	POP	AX					; vytiahneme pocet znakov retazca, ktory sme si odlozili
	SUB	AL, CL					; miesto = celkovy pocet - pocet do konca retazca
	ADD	AL, 1					; nakolko 1.znak by oznacilo ako nulty, "opravime" to

	MOV	CL, 100					; vypis miesta vyskytu znaku:
	DIV	CL					; zistenie stoviek
	PUSH	AX					; zaloha (aj) zvysku po deleni, ktory bude este treba
	ADD	AL, '0'					; zmena cisla na znak reprezentujuci dane cislo
	MOV	DL, AL
	MOV	AH, 02					; vypisanie stoviek (volanie sluzby)
	INT	21H
	STC

	POP	AX					; vytiahnutie (aj) zvysku po deleni s predoslej operacie
	MOV	AL, AH
	MOV	AH, 0
	MOV	CL, 10					; zistovanie desiatok
	DIV	CL
	PUSH	AX					; zaloha (aj) zvysku po deleni (cize jednotiek)
	ADD	AL, '0'					; zmena cisla na znak reprezentujuci dane cislo
	MOV	DL, AL
	MOV	AH, 02					; vypisanie desiatok (volanie sluzby)
	INT	21H

	POP	AX					; vytiahnutie (aj) zvysku po deleni (cize jednotiek)
	MOV	AL, AH
	ADD	AL, '0'					; zmena cisla na znak reprezentujuci dane cislo
	MOV	DL, AL
	MOV	AH, 02					; vypisanie jednotiek (volanie sluzby)
	INT	21H
	
	JMP	zac					; navrat na MENU

CODE	ENDS						;koniec kodoveho segmentu
	END	START


; -------------------------------------------------------------------------------------------
; Program je plne funkcny (vykonava vsetky pozadovane operacie)
; bol programovany a testovany na pocitaci AMD Duron pod WindowsXP
; Nakolko vyuziva iba zakladnu sadu instrukcii, nema ziadne zvlastne naroky na procesor
;  a malo by byt mozne ho spustit na ktoromkolvek pocitaci radu x86

; Vstupne udaje (retazec) je obmedzeny podla zadania - cize 100 znakov
; Upravou programu by sme mohli odstranit vypisovanie nepotrebnych (prednych) nul pri vypise pozicie znaku

; POZN.: Pri BIOSovskej sluzbe nacitavania retazcu som musel zadat pocet znakov o jeden viac
;        ako je pozadovany, nakolko sluzba povoluje vzdy o znak menej