; ZADANIE c.1
; Napiste program, ktory nacita z klavesnice text (max.retazec 100 znakov)
; a podla ponukaneho menu vykona  tieto ulohy:
; 
; a)	vypise nacitany retazec
; b)	vykona jednu cinnost
; c)	ukonci vykonavanie programu
; 
; Ponuka cinností:
; 4-  vypise povodne nacitany retazec v obratenom poradi a vypise pocet
;     jeho znakov
;
; Po vykonaní zvolenej moznosti sa program vrati na vypis menu.
;
;--------------------------------------------------------------------------
; 
; Autor: Matej S~ustr
; Termin odovzdania: 14.10.2003
; 3. rocnik, kruzok SI-4
; sk. rok 2003/2004
;
;--------------------------------------------------------------------------
;
; Kompilacia:
;   tasm /ml /m5 /n /z /zi /q zad1.asm
;   tlink /x /n zad1
;
;**************************************************************************



model small
.8086

MAXLENGTH	equ 100		;definicia max. dlzky vstupu, podla zadania
				;to ma byt 100

.data?
textinp	db ?			;toto pojde sluzbe 0Ah
				;max. velkost, co sa ma nacitat
textcnt	db ?			;kolko sa nacitalo
text	db MAXLENGTH+1 dup(?)	;sem sa ulozi nacitany retazec
				;+1 je kvoli NULL ukonceniu, co tam DOS da

xpocet	db 3 dup(?)		;pocet ako text, ale >'255' to nemoze byt
				;lebo to funkcia 0Ah nezvlada, takze
				;nepotrebujeme viac

.data
t_zac	db 'Zadaj retazec (max. 100 znakov):'
t_nl	db 13,10,'$'		;newline
t_menu	db '1. vypis retazec',13,10
	db '2. vykonaj funkciu - obrateny retazec, pocet znakov',13,10
	db '3. koniec',13,10,'$'
t_zlem	db 'Nepodporovana volba! Skus jednu z tychto:',13,10,'$'

t_povod	db 'Povodny retazec:$'
t_obr	db 'Obrateny retazec:$'
t_pocet	db 'Pocet znakov:$'


.code

;*** vypis na obrazovku je casto pouzivany, pre prehladnost ako makro...
VYPIS1 	macro txt
	mov	ah, 09
	mov	dx, offset txt
	int	21h
endm
VYPISx	macro txt		;ak je viac vypisov za sebou, netreba ah=09
	mov	dx, offset txt
	int	21h
endm


;*** hl.program ***********************************************************
start:
	;* vypis hlasku, ze sa ma zadat retazec
	mov	ax, @data
	mov	ds, ax
	VYPIS1	t_zac

	;* nacitaj retazec
	mov	ah, 0ah
	mov	dx, offset textinp
	mov	byte ptr [textinp], MAXLENGTH+1	;nastavime maximum
	int	21h		;+1 je kvoli DOSovemu NULL na konci retazca

	VYPIS1	t_nl		;posun na novy riadok

menu:
	VYPIS1	t_menu
	;* zisti volbu
	mov	ah, 0ch		;najprv vyprazdni klav. buffer a potom
	mov	al, 08h		;nacita 1 znak z klavesnice (bez vypisania)
	int	21h
	cmp	al, '1'
	je	vypis_retazec	;uloha a
	cmp	al, '2'
	je	vypis_obrateny	;uloha b
	cmp	al, '3'
	jne	menu_zlavolba	;je na koniec ku quit by bolo out of range
	jmp	quit		;uloha c

menu_zlavolba:			;hocico ine okrem 1,2,3 je zle
	VYPIS1	t_zlem
	jmp	menu

;--- uloha a --------------------------------------------------------------
vypis_retazec:
;* vypise retazec na obrazovku -- pouziva 02 a nie 09, aby sa dal vypisat $

	VYPIS1	t_povod
	xor	cx, cx		;cx=0
	mov	cl, [textcnt]	;pocet znakov textu
	jcxz	vypis_ret_end	;prazdny retazec, aby nam to nepodtieklo
	mov	si, offset text
	mov	ah, 02		;funkcia vypisu 1 znaku
  vypis_ret_loop:
	mov	dl, [si]	;ta funkcia vypise znak z DL
	inc	si
	int	21h
	loop	vypis_ret_loop	;postupne po znakoch vypiseme cely retazec
  vypis_ret_end:		
	VYPIS1	t_nl		;posun na novy riadok
	jmp	menu		;navrat do menu

;--- uloha b --------------------------------------------------------------
vypis_obrateny:
;* vypise retazec na obrazovku obratene

	VYPIS1	t_obr
	xor	cx, cx
	mov	cl, [textcnt]
	jcxz	vypis_obr_pocet	;prazdny retazec, aby nam to nepodtieklo
	mov	si, offset text
	add	si, cx
	mov	ah, 02		;vypis 1 znaku
  vypis_obr_loop:
	dec	si		;vypisujeme obratene
	mov	dl, [si]
	int	21h
	loop	vypis_obr_loop

  vypis_obr_pocet:
	VYPIS1	t_nl		;posun na novy riadok

;* vypise pocet znakov retazca (v textovej forme)

	VYPISx	t_pocet
	mov	di, offset xpocet
	xor	ax, ax		;pocet znakov
	mov	al, [textcnt]
	mov	bl, 10		;budeme delit 10
convert_loop:
	div	bl
	add	ah, '0'		;chceme zvysok
	mov	[di], ah	;ulozime
	inc	di
	mov	ah, 0		;a zmazeme, nech sa da dalej delit
	test	al, al
	jnz	convert_loop	;ak este nie je 0, pokracujeme

	;cislo mame v obratenom poradi, tak ho vypiseme odzadu
	mov	cx, di
	sub	cx, offset xpocet	;zistime pocet znakov cisla
	mov	ah, 02		;sluzba vypisu
  vypis_c_loop:
	dec	di		;vypisujeme odzadu
	mov	dl, [di]
	int	21h
	loop	vypis_c_loop
	
	VYPIS1	t_nl		;posun na novy riadok
	jmp	menu

;--- uloha c (koniec) -----------------------------------------------------

quit:
	mov	ax, 4c00h
	int	21h
end start



;**************************************************************************
;
; Zhodnotenie:
;
; Program je funkcny podla zadania, bol vypracovany v prostredi editora
; Notepad a da sa prelozit cez Turbo Assembler (pozri hlavicku).
; Vstupny retazec nie je obmedzeny, mozeme zadat lubovolny znak, az na
; znak Enter, ktory vstup ukoncuje.
;
; Program vyuziva iba zakladne funkcie DOSu, takze by mal fungovat aj na
; starsich verziach DOSu.
; Vyuziva instrukcie procesora 8086.
;
; Mozne vylepsenia:
; - menu ovladatelne sipkami
; - farebne rozlisenia
; - handling prerusenia pri stlaceni Ctrl-C (aby vypisal peknu hlasku)
;
; Popis vlastnych pouzitych algoritmov:
; - vypis retazca na obrazovku robim pomocou sluzby 02h, ci uz v priamom
;   alebo obratenom poradi, pouzivam na to loop
; - vypis cisla robim pomocou konverzie na text v opacnom poradi (pouzitim
;   zvyskov po deleni 10), ktory potom odzadu vypisem
;
; Upozornenie na taktiky a finty, ktore pouzil tvorca programu:
; - standardny vypis na obrazovku pomocou sluzby 09h som zakomponoval ako
;   makro, aby som sprehladnil program
; - nepouzivam instrukciu "MOV reg, 0", pretoze je pomala a zabera po 
;   prelozeni viac bytov kodu. Namiesto nej pouzivam "XOR reg, reg", ktora
;   je na procesore 8086 o 1 instrukcny cyklus rychlejsia.
; - pouzivam TASM notaciu .code/.data atd., pretoze je jednoduchsia ako
;   explicitne definovanie segmentov
;

;EOF