;Zadanie c.2
;Text konkretneho zadania:
;Vytvorte  program,  ktory  nacita  z  textoveho suboru postupnost celych
;cisel (viac ako 5) so znamienkom  v desiatkovej ciselnej sustave. 
;Precitane cisla transformujte na cisla v dvojkovej ciselnej sustave
;v doplnkovom kode, potom ich usporiadajte a scitajte vsetky zaporne cisla 
;Autor:Jaroslav Ziak  
;Termin odovzdania: 02.12.2003
;3.roc, sk.rok 2003/2004

.model small
.stack 100h

DATA     SEGMENT

CHYBA1  DB        10,13,'Nepodarilo sa otvorit(vytvorit) subor!$'          ;chybove hlasenia
CHYBA2  DB        10,13,'Nepodarilo sa nacitat data!$'
CHYBA3  DB        10,13,'Nepodarilo sa zatvorit subor!$'
CHYBA4  DB        10,13,'cislo mimo rozsahu -32768 ; 32767!$'

INFO0   DB        10,13,'Stlacte klaves!$'                                 ; pomocne vypisi na informovanie pouzivatela 
INFO2   DB        10,13,'Praca so suborom...$'

NL	DB	  10,13,'$'

text1   DB        10,13,10,13,'Nacitane cisla: ',10,13,'$'                 ; pomocne vypisi informujuce co sa vypisalo na   
text2   DB        'Suma cisel:','$'                                 ; na obrazovku
text3   DB        10,13,10,13,'Usporiadavam...',10,13,'$'                  ; popripade aka akcia prebehla 


VSTUP   DB        'VSTUP.TXT',0                                            ; nazov vstupneho suboru
VYSTUP  DB        'VYSTUP.TXT',0                                           ; nazov vystupneho suboru  


LDATA   DB        255 DUP(0)                                               ;sem ukladam nacitane data a pracujem s nimi
POCET   DB        0,0

SUCET   DB        10,13,'Sucet zapornych cisiel je: ',10,13,'$'            ; pomocny vypis

cislo_zobraz DB '      ',13,10,'$'                                         ;sablona pre zobrazenie cisla   
cislo_zob    DB '      ',13,10,'$'

DATA     ENDS

CODE     SEGMENT
         ASSUME  CS:CODE, DS:DATA                                          ; priradenie segmentov  


;stlacenie lubovolnej klavesy

proc klaves 
	  mov DX, OFFSET INFO0	                                             ;stlac lub.klavesu
        mov AH, 09H                                                        ;vypisanie textu pre uzivatela
        int 21H                                                            ;zavolanie prerusenia
        mov ah,08H                                                         ;AH=8
	  int 21h			                                             ;citame znak s klavesnice [bez vypisu]
        ret
klaves endp

;prevod cisla z retazca do cisla dvojkovom doplnkovom kode
RDCISLO PROC                      ;vstupny retazec v BX, vystup AX, znamienko CH, nacital som cislo CL=1 inak CL=0
	  mov bx,offset LDATA
znova_citaj:
        xor cx,cx                 ;nulovanie registrov
	  xor dx,dx
	  xor ax,ax
zistuj:                           ;najdenie cisla v retazci
	  mov dl,[bx]
        cmp dl,47                 ;je to cislo
        ja zistuj1     
        jmp zle                   ;nieje to cislo
zistuj1:
        cmp dl,57                 ;je to cislo
        jna klad                  ;cislo je kladne
zle:                              ;tu sa presvecim ze ci som uz spracoval ucelene cislo
	  cmp cl,1
        jz konret                 ;je v AX ucelene cislo
                                  ;a v CH znamienko
        cmp byte ptr [bx],'-'     ;je to znamienko
	  jz daj_minus
                                  ;nieje to znamienko
        cmp byte ptr [bx],0       ;kontrola konca retazca
	  jz konret
        xor cx,cx                 ;akekolvek znamieko je neplatne
        inc bx                    ;idem na dalsi znak
        jmp zistuj
daj_minus:
        mov ch,1                  ;ak zaporne do CH=1
	  inc bx                    ;posun v retazci
        jmp zistuj                ;dalsi znak
klad:	  mov cl,1                  ;nacital som cislo 
	  mov dl,10                 ;priprava na nasobenie desiatimi
	  mul dx                    ;cislo uz prelozene v AX vynasoby desiatimi
	  mov dl,[bx]               ;nacitanie znaku cisla
        sub dl,30h                ;znak->cislo
	  add ax,dx                 ;pripocitanie k uz prelozenemu cislu
        inc bx                    ;pohyb v retazci
        jmp zistuj                ;dalsi znak

konret: cmp cl,1		          ;je to ucelene cislo?
        jz rozsah                 ;ak je  tak dalej
	  ret
rozsah: cmp ch,1                  ;ak je cislo zaporne
	  jz mns
	  cmp ax,32767              ;skontrolovanie maximalnej hodnoty kladneho cisla
        ja chyba                  ;ak nepasuju rozsahy cislo neratame do nasej databazi
	  jmp uloz_cislo
mns:	  cmp ax,32768              ;skontrolovanie maximalnej hodnoty zaporneho cisla
        ja chyba                  ;ak nepasuju rozsahy cislo neratame do nasej databazi 
uloz_cislo:
				          ;v ch reg. je znamienko este ho nespracuvam
	  push bx			    ;ulozim bx
	  mov bx,offset POCET	    ;do bx dam adresu POCET
	  mov dh,[bx]		    ;do dx ulozim hodnotu, ktora je na POCET
	  inc bx                    ;inkrementujem bx
	  mov dl,[bx]		    ;do dx ulozim hodnotu, ktora je na POCET
	  mov bx,offset LDATA	    ;do bx dam adresu LDATA	
	  add bx,dx		          ;bx=bx+dx
	  cmp ch,1		          ;je to zaporne cislo
	  jnz kladne_c		    ;ano, dam ho do doplnkoveho kodu
	  not ax			    ;ak ano neguj AX
	  add ax,1		          ;pripocitaj 1
kladne_c:
	  mov [bx],ah		    ;na adresu bx ulozim AH reg.
	  inc bx			    ;bx=bx+1
	  mov [bx],al		    ;na adresu bx, ulozim al
				          ; [ah][al],[ah][al],...
	  add dx,2		          ;dx=dx+2
	  mov bx,offset POCET	    ;do bx dam adresu POCET
	  mov [bx],dh		    ;do dx ulozim hodnotu, ktora je na POCET
	  inc bx
	  mov [bx],dl		    ;do dx ulozim hodnotu, ktora je na POCET
	  pop bx			    ;obnovim bx
	  jmp znova_citaj		    ;nacitaj dalsie cislo
chyba:                            ;nepasuju rozsahy
        mov DX, OFFSET CHYBA4     ;doslo k chybe, vypis chyboveho hlasenia
	  mov AH, 09H
	  int 21H
	  jmp koniec		    ;skonci program
RDCISLO ENDP

;vypis cisla 
vypiscislo proc          
                                  ;cislo je v ax                   
        mov bx,offset cislo_zobraz;nacitanie sablony
        push ax                   
        pop ax
        rcl ax,1                  ;rotujem do lava CF=znamienko
        jnc plus                  ;ak plus tak dalej
        mov dl,'-'                ;takze minus
        mov [bx],dl               ;ulozenie -
        inc bx
        rcr ax,1                  ;rotujem do prava CF=znamienko(vratim)
        sub ax,1                  ;odcitame jednotku
        not ax			    ;negujeme bx
        rcl ax,1                  ;rotujem do lava CF=znamienko
plus:                             ;pre vypis
        rcr ax,1                  ;odrotujem set
        xor cx,cx                 ;cislo je v AX
s10000: cmp ax,10000
        jb s1001
        sub ax,10000
	  inc cl			    ;v cl je cislica
	  jmp s10000
s1001:  cmp cl,0
	  jz s1000
	  add cl,30h		    ;ak nieje nula vypis cislice
	  mov [bx],cl
	  inc bx
s1000:  cmp ax,1000
	  jb s101
	  sub ax,1000
	  inc ch			    ;v ch je cislica
	  jmp s1000
s101:	  cmp ch,0		
	  jnz s103
	  cmp cl,0		          ;ak cislica=0
	  jz s100			    ;a predosla cislica=0 skok na s100
s103:	  add ch,30h		
        mov [bx],ch               ;inak vypise cislicu
	  inc bx
s100:   xor cl,cl		          ;zmaz predoslu cislicu
s102:	  cmp ax,100		    ;spocita pocet 100
	  jb s10
	  sub ax,100
	  inc cl
	  jmp s102
s10:	  cmp cl,0
	  jnz s13
	  cmp ch,0
	  jz s12
s13:	  add cl,30h		    ;prida 30h k poctu 100-viek
        mov [bx],cl               ;vypise desiatky
        inc bx
s12:    xor ch,ch
s11:	  cmp ax,10
	  jb s1
	  sub ax,10		          ;spocita 10-tky
	  inc ch
	  jmp s11
s1:     cmp ch,0
	  jnz s3
	  cmp cl,0
	  jz s002
s3:	  add ch,30h		    ;prida 30h
        mov [bx],ch               ;vypise desiatky
	  inc bx
s002:   add ax,30h		    ;vypise jednotky
        mov [bx],al     
znovanuluj:
	  inc bx
	  mov dl,[bx]
	  cmp dl,13
	  jz koniec_vyp
	  mov dl,' '		    ;' '
	  mov [bx],dl
	  jmp znovanuluj
koniec_vyp: 
        ret
vypiscislo endp

vypiscislo1 proc          
                                  ;cislo je v ax                   
        mov bx,offset cislo_zob   ;nacitanie sablony
        push ax                   
        pop ax
        rcl ax,1                  ;rotujem do lava CF=znamienko
        jnc pplus                  ;ak plus tak dalej
        mov dl,'-'                ;takze minus
        mov [bx],dl               ;ulozenie -
        inc bx
        rcr ax,1                  ;rotujem do prava CF=znamienko(vratim)
        sub ax,1                  ;odcitame jednotku
        not ax			    ;negujeme bx
        rcl ax,1                  ;rotujem do lava CF=znamienko
pplus:                             ;pre vypis
        rcr ax,1                  ;odrotujem set
        xor cx,cx                 ;cislo je v AX
ps10000: cmp ax,10000
        jb ps1001
        sub ax,10000
	  inc cl			    ;v cl je cislica
	  jmp ps10000
ps1001:  cmp cl,0
	  jz ps1000
	  add cl,30h		    ;ak nieje nula vypis cislice
	  mov [bx],cl
	  inc bx
ps1000:  cmp ax,1000
	  jb ps101
	  sub ax,1000
	  inc ch			    ;v ch je cislica
	  jmp ps1000
ps101:	  cmp ch,0		
	  jnz ps103
	  cmp cl,0		          ;ak cislica=0
	  jz ps100			    ;a predosla cislica=0 skok na s100
ps103:	  add ch,30h		
        mov [bx],ch               ;inak vypise cislicu
	  inc bx
ps100:   xor cl,cl		          ;zmaz predoslu cislicu
ps102:	  cmp ax,100		    ;spocita pocet 100
	  jb ps10
	  sub ax,100
	  inc cl
	  jmp ps102
ps10:	  cmp cl,0
	  jnz ps13
	  cmp ch,0
	  jz ps12
ps13:	  add cl,30h		    ;prida 30h k poctu 100-viek
        mov [bx],cl               ;vypise desiatky
        inc bx
ps12:    xor ch,ch
ps11:	  cmp ax,10
	  jb ps1
	  sub ax,10		          ;spocita 10-tky
	  inc ch
	  jmp ps11
ps1:     cmp ch,0
	  jnz ps3
	  cmp cl,0
	  jz ps002
ps3:	  add ch,30h		    ;prida 30h
        mov [bx],ch               ;vypise desiatky
	  inc bx
ps002:   add ax,30h		    ;vypise jednotky
        mov [bx],al     
pznovanuluj:
	  inc bx
	  mov dl,[bx]
	  cmp dl,13
	  jz pkoniec_vyp
	  mov dl,' '		    ;' '
	  mov [bx],dl
	  jmp pznovanuluj
pkoniec_vyp: 
        ret
vypiscislo1 endp

;vypis vsetkych cisel
vypis proc			          ;vypis cisel 
        mov bx,offset POCET	    ;do bx dam adresu POCET
	  mov dh,[bx]		    ;do dx ulozim hodnotu, ktora je na POCET
	  inc bx
	  mov dl,[bx]
	  mov bx,offset LDATA	    ;do bx dam adresu LDATA
	  add dx,bx		          ;aby som vedel aka je adresa konca pola
zase:	
	  mov ah,[bx]		    ;ah dam horne bity
	  inc bx
	  mov al,[bx]		    ;do al dam dolne bity
	  inc bx
	  push dx			
	  push bx			    ;registe porebujem mat zachovane
	  call vypiscislo		    ;v ah,al registoch ma byt hodnota v doplnkovom kode
	  mov dx,offset cislo_zobraz; vypis cisla
	  mov AH, 09H
	  int 21H
	  pop bx
	  pop dx
	  cmp bx,dx		          ;som na konci pola?
	  jnz zase		          ;ak nie znova vypis cislo
        ret
vypis endp

;suma vsetkych zapornych cisel 
SUMAcisel proc
        mov bx,offset POCET       ;do bx dam adresu POCET
        mov dh,[bx]               ;do dx ulozim hodnotu, ktora je na POCET
        inc bx                    
        mov dl,[bx]
        mov bx,offset LDATA       ;do bx dam adresu LDATA
        add dx,bx                 ;aby som vedel aka je adresa konca pola
        xor cx,cx                 ;vynulujem pocitadlo
znova_pocitaj:
        mov ah,[bx]               ;ah dam horne bity
        inc bx
        mov al,[bx]               ;do al dam dolne bity
        inc bx
        cmp ax,32768              ;ak nie je vacsie ako 32768(je kladne tak preskoc) 
        jna preskoc
        add cx,ax                 ;cx=cx+ax ..v cx je sucet
preskoc:cmp bx,dx                 ;je to koniec pola s hodnotami
        jnz znova_pocitaj         ;ak nie spocitaj dalsie cislo
        mov ax,cx                 ;ax,cx
        call vypiscislo1          ;v ah,al registoch ma byt hodnota v doplnkovom kode
        mov dx,offset cislo_zob   ; vypis cisla na obrazovku
        mov AH, 09H
        int 21H
        ret
SUMAcisel endp

;usporiadanie cisel
usporiadaj proc
opet_otoc:
        mov bp,0                  ;zatial nebol pokus o znovuotocenie
        mov bx,offset POCET	    ;do bx dam adresu POCET
	  mov dh,[bx]		    ;do dx ulozim hodnotu, ktora je na POCET
	  inc bx                    ;bx inkrementujem
	  mov dl,[bx]               ;do dl dam hodnotu ktora je na pozici bx
	  mov bx,offset LDATA	    ;do bx dam adresu LDATA
	  add dx,bx		          ;aby som vedel aka je adresa konca pola
znova_poc:
	  mov ah,[bx]		    ;ah dam horne bity
	  inc bx
        mov al,[bx]               ;do al dam dolne bity
	  inc bx
        mov ch,[bx]               ;ch dam horne bity
	  inc bx
        mov cl,[bx]               ;do cl dam dolne bity
	  inc bx
	  cmp ax,32768		    ;je to zaporne cislo?
	  ja ax_zap		          ;ak ano
	  cmp cx,32768		    ;je to zaporne cislo?
	  ja rozne_zmnamienka	    ;ak ano (predosle nie)
rovnake_znamienka:
	  cmp ax,cx	                ;teda obe cisla su kladne(zaporne)
	  jb neotacaj               ;netocim ak je CX>=AX  
	  jz neotacaj		
	  xchg ax,cx	          ;inak ich musim otocit
	  jmp otacaj
ax_zap:
	  cmp cx,32768		    ;je v cx zaporne
	  ja rovnake_znamienka	    ;ano maju rovnake minusove znamienka
rozne_zmnamienka:                 ;teda obe cisla maju rozne znamienka
	  cmp ax,cx	
	  ja neotacaj               ; ak je CX>=AX 
	  jz neotacaj		
	  xchg ax,cx	          ;inak ich musim otocit
otacaj:
	  mov bp,1                  ;informacia ze doslo k otoceniu  
	  sub bx,4
	  mov [bx],ah		    ;ah dam horne bity
	  inc bx
	  mov [bx],al		    ;do al dam dolne bity
	  inc bx
	  mov [bx],ch		    ;ah dam horne bity
	  inc bx
	  mov [bx],cl		    ;do al dam dolne bity
	  inc bx
neotacaj:
	  cmp bx,dx		          ;zistim ci je koniec retazca
	  jz koniec_ot	
	  sub bx,2		          ;ak nie, idem na dalsiu dvojicu
 	  jmp znova_poc
koniec_ot:
	  cmp bp,1			    ; zistim ci doslo k vymene
	  jz opet_otoc              ; ak ano idem znovu
	  ;vystup do suboru        
	  ;tu potrebujem zalozit subor
	  mov DX, OFFSET INFO2	    ;vypis pre pouzivatela
	  mov AH, 09H               
	  int 21H
        mov AH, 3cH               ;vytvorenie suboru
        mov DX, OFFSET VYSTUP     ;adresa ASCII  retazca mena suboru
	  mov CX, 0		          ;nejake atributy souboru
	  int 21H			
        jnc no
        mov DX, OFFSET CHYBA1     ;doslo k chybe
	  mov AH, 09H
	  int 21H
        jmp koniec		
			                ;inak je AX rukojet suboru
No:                               ;nacitanie zo suboru
	  mov CX,AX		          ;rukojet budeme potrebovat pri zatvarani
	  push CX
	  mov bx,offset POCET	    ;do bx dam adresu POCET
	  mov dh,[bx]		    ;do dx ulozim hodnotu, ktora je na POCET
	  inc bx
	  mov dl,[bx]
	  mov bx,offset LDATA	    ;do bx dam adresu LDATA
	  add dx,bx		          ;aby som vedel aka je adresa konca pola
zase00:	
	  mov ah,[bx]		    ;ah dam horne bity
	  inc bx
	  mov al,[bx]		    ;do al dam dolne bity
	  inc bx
	  push dx			
	  push bx			    ;registe porebujem mat zachovane
     	  call vypiscislo		    ;v ah,al registoch ma byt hodnota v doplnkovom kode
	  pop bx
	  pop dx
	;tu to potrebujem zapisat do suboru	
	  pop cx			    ;ziskanie rukojete
        push cx
	  push dx			
	  push bx			    ;registe porebujem mat zachovane
	  mov ah,40h		    ;zapis do suboru
	  mov bx,cx			    ;pre toto ten 'tah'
	  mov dx,offset cislo_zobraz;vypis cisla
        mov cx,8                  ;pocet
	  int 21H
	  pop bx
	  pop dx
	  cmp bx,dx		          ;som na konci pola?
	  jnz zase00		    ;ak nie znova vypis cislo
	  pop cx
        push cx
        mov ah,40h		    ;zapis do suboru
	  mov bx,cx			    ;do bx file handle suboru
	  mov dx,offset cislo_zob   ;vypis sumy zapornych cisel do suboru
        mov cx,8                  ;pocet
	  int 21H

        pop CX
	  mov bx,cx
	  mov AH, 3eH		    ;zavretie vstupneho suboru
	  int 21H
	  jnc koniec_usp
        mov DX, OFFSET CHYBA3     ;doslo k chybe
	  mov AH, 09H
        int 21H
        jmp koniec		
koniec_usp:
	  ret
usporiadaj endp

START:  mov AX, SEG DATA          ;nacitanie datoveho segmentu 
        mov DS, AX                ; v DS zac. adresa dat. segmentu 
;-nacitanie cislic so suboru do retazca LDATA-
OPENfile:
	  mov AH, 3dH               ;otvorenie suboru na citanie
        mov DX, OFFSET VSTUP      ;adresa ASCIIZ  retazca mena suboru
	  mov AL, 0		          ;subor na nacitavanie
	  int 21H			    ;zavolanie dosovskej funkcie
	  jnc LOADdata              ;ak nedoslo k chybe pri otvarani, tak skoc na nacitavanie
        mov DX, OFFSET CHYBA1     ;doslo k chybe
	  mov AH, 09H               ;vypis chyboveho hlasenia 
	  int 21H
        jmp koniec		
				          ;AX -rukojet suboru
LOADdata:			          ;nacitanie zo suboru
        mov BX, AX                ;premiestni rukojet do BX (budem potrebovat pri zatvarani suboru)
        mov AH, 3fH               ;pre ncitavanie
        mov DX, OFFSET LDATA	    ;nacitavam do LDATA
        mov CX, 255		    ;maximalne 255 znakov	;tu 
        int 21h                   ;v AX je pocet skutocne precitanych bitov
	  jnc CLOSEfile             ; ak bez chyby skoc na zatvorenie
        mov DX, OFFSET CHYBA2     ;doslo k chybe
	  mov AH, 09H               ;vypis chyby
	  int 21H                    
        jmp koniec		
	
CLOSEfile:
	  mov AH, 3eH		    ;zavretie vstupneho suboru
	  int 21H

	  jnc PREVODbin             ;ak bez chyby tak skoc na prevod
        mov DX, OFFSET CHYBA3     ;doslo k chybe
	  mov AH, 09H               ;vypisanie chyby  
	  int 21H
        jmp koniec		
PREVODbin: 
        call RDCISLO              ;zavolanie procedury na prevod 
        mov DX,offset text1	    ;vypis textu
	  mov AH, 09H
	  int 21H
        call vypis                ;vypis znakov
        call klaves               ;cakaj na stlacenie lub klavesy         
        mov DX,offset text2       ;vypis textu
        mov AH, 09H
        int 21H
        call SUMAcisel            ;zavolanie procedury na sumu zapornych cisel
        call klaves               ;cakaj na stlacenie lub klavesy
	  mov DX,offset text3	    ;vypis textu
	  mov AH, 09H
	  int 21H
	  call Usporiadaj           ;zavolanie procedury na usporiadanie cisel 
        call klaves               ;cakaj na stlacenie lub klavesy
koniec: mov AX,4C00H              ;ukoncenie programu  
        int 21H
CODE    ENDS
        END       START

;ZAVER:
; Moj program je plne funkcny a splna vsetky atributy pozadovane v zadani. Bol napisany vo Wordpad-e,
; prelozeny bol v programe  Turbo Assembler ver. 3.1 a linkovany v programe Turbo Link ver. 5.1.
; Pouzita sada instrukcii procesora 80x86. 
; Program vykonava vsetky funkcie podla zadania.
; Najprv vykona nacitanie zo suboru, vypise nacitane cisla na obrazovku, potom vypise sumu cisel a nakoniec cisla
; usporiada a zapise ich do suboru a na koniec za ne prida sumu zapornych cisel.
; Obmedzenia programu: program spracovava iba cisla od -32768 do 32767,
; ich pocet je ohraniceny velkostou suboru, z ktoreho nacitava. Max. velkost suboru je 259 bytov. 
; Vylepsit by sa dala graficka uprava programu.
