;info: zadanie sa mi podarilo zbuchat na plny pocet vdaka zdrojakom,
;ktore boli na Marvinovi, preto prispejem i ja svojimi, mozno vam
;tiez pomozu... enjoy ;)


;.==================================================================.
;|'================================================================'|
;||                                                                ||
;||                                  .::::.                        ||
;||                                .::::::::.                      ||
;||                                :::::::::::                     ||
;||                                ':::::::::::..                  ||
;||                                 :::::::::::::::'               ||
;||                                  ':::::::::::.                 ||
;||                                    .::::::::::::::'            ||
;||                                  .:::::::::::...               ||
;||                                 ::::::::::::::''               ||
;||                     .:::.       '::::::::''::::                ||
;||                   .::::::::.      ':::::'  '::::               ||
;||                  .::::':::::::.    :::::    '::::.             ||
;||                .:::::' ':::::::::. :::::      ':::.            ||
;||              .:::::'     ':::::::::.:::::       '::.           ||
;||            .::::''         '::::::::::::::       '::.          ||
;||           .::''              '::::::::::::         :::...      ||
;||        ..::::                  ':::::::::'        .:' ''''     ||
;||     ..''''':'                    ':::::.'                      ||
;|'================================================================'|
;||  Zadanie c. 1:                                                 ||
;||  Napiste program, ktory po nacitani maximalne 80-znakoveho     ||
;||  retazca spusti procesy podla nastaveneho daneho bitu registra ||
;||  BH takto:  1.bit - najde znak s max. hodnotou                 ||
;||                     a vypise tento znak a jeho poziciu         ||
;||             6.bit - usporiada sa nacitany retazec              ||
;||                     a vypise sa vysledok                       ||
;||  Ak nebudu  uvedene bity nastavene, program o tom vypise       ||
;||  prislusnu spravu, ak bude obsah registra BH nula, vlozte nulu ||
;||  do pamati na adresu, ktora je aktualnym vrchom zasobnika.     ||
;||  Meno: Lubomir Salaj                                           ||
;||  Termin odovzdania: 30.03.2007                                 ||
;||  Rocnik: 2., akademicky rok: 2006/2007                         ||
;'=====overclocker=============================l33t since '84======='



DATA     SEGMENT    ; zaciatok dat.segmentu
TEXT2     DB        10,13,'Zadany retazec: $'
menu0     DB        10,13,'Zatlac zodpovedajucu klavesu:$'
menu1     DB        10,13,'1-Vypise zadany retazec na nas monitor$'
menu2     DB        10,13,'2-Nacita novy retazec$'
menu3     DB        10,13,'3-Testy 1. a 6. bitu a vykonanie uloh$'
menu4     DB        10,13,'4-Nastavenie 1. bitu registra BH$'
menu5     DB        10,13,'5-Nastavenie 6. bitu registra BH$'
menu6     DB        10,13,'6-Koniec',10,13,'$'
riadok    DB        10,13,'$'
theend    DB        'dovidenia!$'
vstup     DB        81
pocet     DB        0
          DB        81 dup(?)
kopia     DB        81 dup('$')
zadaj     DB        10,13,'Zadaj string: $'
vyska     DB        1 dup (0)
poradie   DB        0
BEHAPRV0  DB        10,13,'Prvy bit je 0, uloha sa nevykona!$'
BEHAPRV1  DB        10,13,'Prvy bit je 1, uloha sa vykona po stlaceni klavesy$'
BEHASIE0  DB        10,13,'Siesty bit je 0, retazec sa neusporiada$'
BEHASIE1  DB        10,13,'Siesty bit je 1, stlac klavesu pre usporiadanie$'
BEHACENU  DB        10,13,'Cely BH je nulovy, na vrch zasobnika davam 0$'
PRESS     DB        10,13,'Press any key to continue...$'
NAJVYSSI  DB        10,13,'Najvyssim znakom je "$'
POZICIA   DB        '" a nachadza sa na pozicii $'
NASTAVIT1 DB        10,13,'Na aku hodnotu mam nastavit 1. bit BH registra?$'
NASTAVIT6 DB        10,13,'Na aku hodnotu mam nastavit 6. bit BH registra?$'
CHYBA     DB        10,13,'Zadajte hodnotu 0 alebo 1!$'
NASTAVENE DB        10,13,'Bit uspesne nastaveny$'
UPRATANE  DB        10,13,'Usporiadany retazec: $'
STAV1     DB        0
STAV6     DB        0
DATA     ENDS

CODE     SEGMENT
         ASSUME    CS:CODE, DS:DATA
;---------------------------------------NACITANIE RETAZCA-----------------------
nacitaj     proc    ; procedura na nacitanie retazca
           mov ax,seg vstup
           mov ds,ax   ; adresa vstupneho retazca
           mov dx, offset vstup
           mov ah,0ah
           int 21h
            mov al,[vstup+1]  ; pridanie ukoncovacich znakov
            mov bx,offset vstup+2  ;odkaz na zaciatok retazca
           xor ah,ah     ;nulovanie ah, aby sme v dalsom kroku pridali len AL
           add bx,ax    
           mov byte ptr [bx],13        ;pridanie enteru
           mov byte ptr [bx+1],10
           mov byte ptr [bx+2],'$'     ;a pridanie ukoncovacieho znaku
           ret
           endp
;--------------------------------------VYPIS RETAZCA----------------------------
vypisret    proc     ; procedura na vypis retazca
            mov ah,2       ;funkcia na vypis 1 znaku
           mov bx, offset vstup+2    ;odkaz na zaciatok retazca
           xor cx,cx                 ;pripravime si CX register
           mov cl, [bx-1]    ;do CL dame pocet prvkov retazca
 cyklus:   mov dl, [bx]   ; vypisovanie retazca po
           inc bx       ; po znakoch, aby sa osetril
           int 21h     ; $ v retazci
           loop cyklus
           ret
            endp
;------------------------------- PRESS ANY KEY TO CONTINUE...-------------------
pak         proc
            mov DX, offset riadok
            mov ah, 09h
            int 21
            mov dx,offset PRESS
            mov ah, 09h
            int 21h
            mov AH, 08H                  ;pockanie na stlacenie klavesy
            int 21H
            MOV DX, offset riadok
            MOV ah,09h
            int 21h
            ret
            endp
;----------------------ULOHA 3 - VYPISE NAJVYSSI ZNAK A JEHO POLOHU-------------
uloha       proc
            xor CX, CX  ;nuluj CX
            MOV DX, OFFSET VSTUP 
            ADD DX, 2  ; presun sa na zaciatok retazca
            MOV SI, DX  ; v indexovom registri bude offset zaciatku registra
            MOV CL, POCET          ; do cl vloz pocet znakov v retazci
            XOR AH, AH  ; nuluj AH
            XOR BL, BL  ; nuluj BL
            XOR DL, DL  ; nuluj DL  //register bude obsahovat pocitadlo znakov
            MOV VYSKA, BL   ;potrebujem vynulovat aj premenne VYSKA a PORADIE
            MOV PORADIE, BL ;pre pripad, ze uz boli ich hodnoty prepisane
  NASPAT:   MOV BL, [SI]  ; do BL presun znak na ktory ukazuje obsah registra SI
            inc DL        ;v DL mame poradie aktualneho znaku
            CMP BL, vyska  ; porovnaj aktualny znak s dosial najvyssim znakom
            JBE NEXT  ; ak sa je mensi alebo rovny, tak nacitaj dalsi znak
            MOV VYSKA, BL      ;inak do vysky prepis aktualny znak
            MOV poradie, DL     ;a poznac si jeho poziciu
  NEXT:     INC SI   ; presun register SI na dalsi znak retazca
            LOOP  NASPAT  ; skoc ak sa register CX(CL) nerovna nule
            MOV DL, poradie    ;do DL zapis poziciu najvyssieho znaku
            XOR BX ; priprava, sem sa budu davat ASCII hodnoty cifier
            ;prepis z cisla do ASCII
  DESAT:    CMP DL, 10             ; porovnaj hodnotu DL s 10
            JB  JEDNA             ; ak je mensia, skoc na JEDNOT
            SUB DL, 10             ; od DL odpocitaj 10
            INC BL                 ; inkrementuj hodnotu BL (hod. desiatok)
            JMP DESAT             ; skok na DESAT
  JEDNA:    MOV BH, DL             
            ADD BL, 30H            ; do BL prirataj hexadecimalnu nulu
            ADD BH, 30H            ; do BH prirataj hexadecimalnu nulu
            ;vypis na obrazovku
            MOV DX, offset riadok    ;par riadkov obycajnych vypisov
            MOV AH, 09h
            int 21h
            MOV DX, offset NAJVYSSI
            MOV AH, 09h
            INT 21h
            MOV AH, 2              ; funkcia vypis znaku na obrazovku
            MOV DL, VYSKA           ;vypisem hodnotu najvyssieho znaku  
            INT 21H                
            MOV DX, offset POZICIA
            MOV AH, 09h
            INT 21h
            CMP BL, 30h             ;ak je v rade 10tok nula, nevypise sa
            JE  cifra
            MOV DL, BL             ; do DL vloz pocet desiatok - BL
            MOV AH, 02h             ; vypis
            INT 21H                ; volanie funkcie dosu
  cifra:    MOV DL, BH             ; do DL vloz pocet jednotiek - BH
            MOV AH, 02h             ;vypis
            INT 21H                ; volanie funkcie dosu
           vypismenu riadok
            ret
           endp
;--------------------MAKRO NA VYPIS STATICKYCH TEXTOV---------------------------
vypismenu   MACRO t
            mov dx,offset t
            mov ah,9
            int 21h
            endm
;--------------------------------- ZACIATOK PROGRAMU ---------------------------
START:      mov AX, SEG DATA
            mov DS, AX
            vypismenu zadaj
            call nacitaj
;--------------------------------- VYPIS MENU ----------------------------------
MENU:       vypismenu riadok
            vypismenu MENU0
            vypismenu MENU1
            vypismenu MENU2
            vypismenu MENU3
            vypismenu MENU4
            vypismenu MENU5
            vypismenu MENU6
            vypismenu riadok
;-------------------------- NACITANIE VOLBY UZIVATELA --------------------------
VYBER:      mov AH, 08H              ;nacitani znaku, pre vyber z menu
            int 21H
            cmp AL, '1'
            je  M1
            cmp AL, '2'              
            je  M2
            cmp AL, '3'             
            je  M3
            cmp AL, '4'
            je  MO4
            cmp AL, '5'
            je  MO5
            cmp AL, '6'
            je  skonci
            jmp VYBER ;ked zadame inu ako zo 6 moznosti,skoci na vyber od znovu
  MO4:      JMP M4  ;podmienene skoky boli prilis daleko :-/
  MO5:      JMP M5
  skonci:   JMP KONIEC
;-----------------------  1. VYPIS NACITANEHO RETAZCA---------------------------
M1:         call vypisret
            call pak
            jmp MENU                     ;navrat do menu
;------------------------ 2. NACITANIE RETAZCA ---------------------------------
M2:         vypismenu zadaj
            call nacitaj            ; volanie procedury na nacitanie stringu
            jmp MENU                 ;navrat do menu
;---------------------- 3. TEST 1. BITU BH REGISTRA A VYKONANIE ULOHY ----------
M3:         XOR BH, STAV1          ;nastavime bhcko podla premennej stav,
            AND BH, 00000010b     ;ak sme stav v 4ke neupravovali, je to 0
            JZ  JE1NULA           ;andom zistujem, ci je 1.bit jedna, alebo nula
            vypismenu behaprv1    ;ak je nula skoci ine... tu vypise info o 1
            vypismenu riadok
            call pak              
            call uloha            ;a spusti ulohu
            call pak
            JMP TEST6             ;potom ide testovat 6ty bit
  je1nula:  vypismenu behaprv0    
            vypismenu riadok      
            ;call pak
  TEST6:    ADD BH, STAV6         ;do BH prida info o siestom bite
            rol BH, 1             ;2x orotujem
            rol BH, 1
            jc  je6jedna          ;ak sa nastavil carry flag na 1, bola tam 1
            vypismenu behasie0    ;a skocim na je6jedna
            vypismenu riadok
            cmp BH, 0             ;inak porovnam BH s nulou
            jz  zasob             ;a ked je BH prazdne, skocim na zasob
            ;call pak
            jmp MENU
  zasob:    vypismenu behacenu    
            XOR BX, BX          
            PUSH BX               ;a hodim nulu z BX na vrchol zasobnika
            vypismenu riadok
            call pak
            jmp MENU
  je6jedna: vypismenu behasie1    ;ak bol siesty bit jedna, zacnem sortovat
            vypismenu riadok
            call pak
            vypismenu upratane
  usporiadaj:
	         mov si, offset vstup+2 ;najprv musime prekopirovat nas retazec
	         mov di, offset kopia   ;do dalsieho, ktory potom usporiadame
	         mov cl, 1                      
  copy:    mov al,byte ptr[si]     ;tu zaciname kopirovat... nastavime si aj di  
	         mov byte ptr[di],al     ;na rovnaku hodnotu - zaciatok "originalneho"      
	         inc cl                  ;retazca
	         inc di                  ;postupne prenasame znak po znaku...
	         inc si
	         cmp cl,pocet       ;az kym sa pocet znakov v jednom aj druhom retazci           
	         jbe copy           ;nerovna
	         mov bh,1   
  zac:     mov cx,1               ;teraz zacneme so sortom                  
	         mov bl,255             ;do BL dame 255, co je najvyssia ascii hodnota
	         mov si, offset kopia   ;do si dame zaciatok "pracovneho" retazca  
  mam:     cmp bl,[si]            ;dporovnam aktualny znak v si s bl  
	         jbe nemam              ;ak je vacsi, tak skacem prec
	         push si                ;inak ho hodim do zasobnika    
	         mov bl,[si]            ;a do bl si ho poznacim
  nemam:   inc si                 ;prejdeme na dalsie pismeno v retazci
	         inc cx                 ;a zvysime aj pocitadlo znakov
	         cmp cl,pocet           ;zistime, ci sme uz prehladali vsetky znaky
	         jbe mam                ;ak nie, usporiadavame dalej
	         mov dl,bl              ;inak vypisem najmensi zisteny znak
	         mov ah,2                
	         int 21h
	         pop si                 ;vylovim si zo zasobnika
           mov byte ptr[si], 255  ;a prepisem hodnotu, na ktoru ukazuje, na 255
	         inc bh                 ;zvysim bh = pocet usporiadanych znakov
	         cmp bh,pocet           ;usporiadal som vsetky znaky?
	         jbe zac                ;ak nie, ideme od zac(iatku)
	         vypismenu riadok
           call pak
           jmp MENU
;--------------------- 4. NASTAVENIE 1. BITU BHcka -----------------------------
M4:         vypismenu nastavit1    ;vypis
            vypismenu riadok
            mov AH, 01H     ;nacitam znak
            int 21h
            cmp AL, '0'     ;ak 0, bez nizsie
            JE  NULL1
            cmp AL, '1'     ;ak jedna, bez tiez nizsie, ale nie az tak velmi :)
            JE  ONE1
            vypismenu chyba ;ak ina klavesa, upozorni uzivatela o chybe
            jmp M4          ;a caka zas na stlacenie 0 alebo 1
    ONE1:   MOV STAV1, 00000010b ;ak bola stlacena 1, zapise ju do premennej
            vypismenu nastavene ;lebo BH pouzivam v procedurach a mohlo by sa 
            call pak            ;prepisat
            JMP MENU
    NULL1:   MOV STAV1, 00000000b ;podobne ako hore
            vypismenu nastavene
            call pak
            jmp MENU
;------------------------ 5. NASTAVENIE 6. BITU BHcka --------------------------
M5:         vypismenu nastavit6    ;vypis
            vypismenu riadok
            mov AH, 01H     ;nacitam znak
            int 21h
            cmp AL, '0'     ;ak 0, bez nizsie
            JE  NULL6
            cmp AL, '1'     ;ak jedna, bez tiez nizsie, ale nie az tak velmi :)
            JE  ONE6
            vypismenu chyba ;ak ina klavesa, upozorni uzivatela o chybe
            jmp M5          ;a caka zas na stlacenie 0 alebo 1
    ONE6:    MOV STAV6, 01000000b ;ak bola stlacena 1, zapise ju do premennej
            vypismenu nastavene ;lebo BH pouzivam v procedurach a mohlo by sa 
            call pak            ;prepisat
            JMP MENU
    NULL6:   MOV STAV6, 00000000b ;podobne ako hore
            vypismenu nastavene
            call pak
            jmp MENU            
;---------------------------------KONIEC----------------------------------------
KONIEC:     vypismenu theend
            mov AX,4C00H                   ;ukoncenie programu
            int 21H
CODE        ENDS
            END     START


;Zhodnotenie:
;Program funguje vramci zadanych specifikacii bezchybne, je osetreny voci
;nepriazni vstupov pouzivatela (ci uz $ v zadanom retazci alebo neplatne vstupy
;v menu, resp. nastaveniach bitov). Obmedzenie je len na dlzku vstupneho
;retazca, ta bola ale definovana v zadani - 80 znakov. Po tomto limite
;program dalsie znaky neprijima.
;Technicke vybavenie:
;napriek tomu, ze som mal k dispozicii instrukcne sady MMX, SSE, SSE2 i SSE3,
;cielom zadania bolo naucit nas pracovat s instrukcnou sadou zhodnou pre vsetky
;procesory radu x86, preto som vyuzival len tu.
;na kompilaciu som pouzil Turbo Assembler Ver 2.02, na linkovanie suborov som
;pouzil Turbo Link vo verzii 3.01.
;Pripadne vylepsenia programu necham na inych, vsetko, co ma napadlo som do kodu
;zakomponoval ;)
