Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- myStack segment STACK
- dw 100h dup(?)
- myStack ends
- data segment
- blad db "Blad",10,13,"$"
- pomoc db "Poprawna skladnia: konkatenacja [-h|{-i plik_wejsciowy} [-o plik_wyjsciowy] [-t symbol_separacji]]",10,13,"$"
- zla_skladnia db "Bledna skladnia",10,13,"$"
- brak_o db "Nie podano nazwy pliku wyjsciowego!",10,13,"$"
- za_duzo_o db "Podaj tylko jeden plik wejściowy. Opcja -o nie może być użyta wielokrotnie",10,13,"$"
- problem_plik_wejsciowy db "Nie mozna otworzyc pliku do odczytu/zapisu",10,13,"$"
- tmp db 15 dup(0) ;bufor na nazwy plików wejsciowych oraz wyjsciowych
- ile_wejsciowych db 0 ;ile mamy plikow wejsciowych
- plik_wyjsciowy_uchwyt dw 0 ;uchwyt do pliku wyjściowego
- pliki_wejsciowe_uchwyty dw 25 dup(0) ;uchwyty do plików wejściowych
- bools_zrobione db 25 dup(0) ;tablica plików przetworzonych
- bools_czy_pierwszy db 0 ;czy plik na wejściu jest pierwszy w linii, co oznacza brak separatora na początku
- bools_wyjsciowy db 0 ;flaga informujaca czy istnieje plik wynikowy (opcja -o)
- separator db " $" ;domyślnym separatorem jest spacja
- znak db 0,"$" ;pojedynczy znak
- nwln db 13,10,"$" ;nowa linia
- data ends
- code segment
- start:
- main proc
- mov ax,seg data ;ustawianie segment danych
- mov ds,ax
- mov ax,seg myStack ;ustawianie segment stosu
- mov ss,ax ;linia poleceń znajduje sie w es, a jej długość w es:[80h]
- xor cx,cx
- mov cl,es:[80h] ;przechwycenie długości linii komend
- mov di,81h ;parsujemy wejscie od pierwszego znaku
- test cx,cx ; sprawdzamy czy linia komend jest pusta
- je throw_zla_skladnia ;jesli pusta rzucamy blad - na ekran wypluwamy poprawne uzycie
- parsowanie:
- cmp byte ptr es:[di],' ' ;jeśli pierwszy znak nie jest spacją to błąd
- jne throw_zla_skladnia
- inc di
- dec cx
- cmp byte ptr es:[di],'-' ;jeśli kolejny znak nie jest pauzą to błąd
- jne throw_zla_skladnia
- inc di
- dec cx
- if_its_h: ; czy zostal wywolany parametr -h
- cmp byte ptr es:[di],'h'
- je wyswietl_pomoc ; jesli tak wypluj poprawną składnię
- if_its_t: ; czy został wywołany parametr -t
- cmp byte ptr es:[di],'t'
- jne if_its_o
- inc di
- dec cx
- cmp byte ptr es:[di],' ' ;następny znak musi być spacją
- jne throw_zla_skladnia
- inc di
- dec cx
- test cx,cx
- jbe throw_zla_skladnia ; gdy wywolano opcję -t musi się pojawić znak lub spacja
- mov bx,offset separator
- mov al,byte ptr es:[di] ;separator przekazujemy do al
- mov ds:[bx],al ;separator zostaje zmieniony na ten podany w linii komend
- inc di
- dec cx
- test cx,cx
- jbe cmd_is_parsed
- jmp parsowanie
- if_its_o: ;czy jest to wywolanie opcji -o i podanie pliku wynikowego?
- cmp byte ptr es:[di],'o'
- jne if_its_i
- mov bx,offset bools_wyjsciowy
- cmp byte ptr ds:[bx],1 ;Sprawdzam czy nie ma już pliku wyjściowego
- je throw_za_duzo_o
- mov byte ptr ds:[bx],1 ;Zaznaczam że mam już plik wyjściowy
- inc di
- dec cx
- cmp byte ptr es:[di],' ' ;następny znak musi być spacją
- jne throw_zla_skladnia
- inc di
- dec cx
- cmp byte ptr es:[di],' ' ;Jeśli nie ma nazwy pliku wyjściowego to jest to błąd
- je throw_brak_o
- cmp byte ptr es:[di],'-' ;następnym znakiem nie może być "-"
- je throw_zla_skladnia
- ;przekopiowanie nazwy pliku wyjściowego do tmp
- mov bx,offset tmp ;W bx przechowuje offset nazwy pliku wynikowego
- xor si,si ;Aktualny indeks w tablicy tmp
- xor ah,ah
- while_not_space:
- test cx,cx
- jbe after_1_while ;Koniec linii poleceń
- mov al,byte ptr es:[di]
- cmp al,' ' ;jeśli to spacja konczymy kopiowane
- je after_1_while
- mov ds:[bx+si],al ;Wpisuje sobie znak
- inc di
- inc si
- dec cx
- jmp while_not_space
- after_1_while: ;tworzenie i zapis uchwytu do pliku wyjściowego
- mov byte ptr ds:[bx+si],0
- xor si,si ;Pozycja do zapisu uchwytu to zero
- mov bx,offset plik_wyjsciowy_uchwyt ;Tu otrzymam uchwyt
- mov al,010b ;Do odczytu i zapisu
- mov dx,offset tmp
- call fopen
- test cx,cx
- jbe cmd_is_parsed
- jmp parsowanie
- if_its_i: ;czy jest to wywolanie opcji -o i podanie pliku wejsciowego?
- cmp byte ptr es:[di],'i' ;jeśli kolejnym znakiem nie jest "i" - błąd
- jne throw_zla_skladnia
- inc di
- dec cx
- test cx,cx
- jbe throw_zla_skladnia
- cmp byte ptr es:[di],' ' ;następny znak musi być spacja
- jne throw_zla_skladnia
- inc di
- dec cx
- cmp byte ptr es:[di],'-' ; następnym znakiem nie może być "-"
- je throw_zla_skladnia
- mov bx,offset tmp ; tu trzymam offset bufora na nazwę pojedynczego pliku wejsćiowego
- xor si,si ;tu trzymam aktualną pozycję w tablicy bufora
- xor ax,ax
- while_not_space_2: ;Wykonuje sie dopóki parsowany znak to nie spacja lub cx == 0
- test cx,cx
- jbe after_while
- mov al,byte ptr es:[di] ;kopiuje znak do al
- cmp al,' ' ;jeśli aktualny znak to spacja
- je after_while
- mov ds:[bx+si],al ;znak z al kopiuje do bufora
- inc di
- inc si
- dec cx
- jmp while_not_space_2
- after_while:
- mov byte ptr ds:[bx+si],0 ;Poprzednia nazwa mogła być dłuższa
- mov bx,offset ile_wejsciowych
- xor ax,ax
- mov al,byte ptr ds:[bx] ;Pobieram numer uchwytu do zapisu
- mov si,ax
- shl si,1 ;Przemnażam si przez 2 bo lece po wordach
- inc al
- mov byte ptr ds:[bx],al ;Zwiękaszam numer w zmiennej
- mov bx,offset pliki_wejsciowe_uchwyty
- xor ax,ax
- mov dx,offset tmp
- mov al,000b ;Tylko do odczytu
- call fopen
- test cx,cx
- jbe cmd_is_parsed
- jmp parsowanie
- jmp parsowanie
- cmd_is_parsed:
- ;tutaj posiadamy wszystkie potrzebne uchwyty do plików
- xor di,di ;numer odpowiedniego pliku wejściowego do przerabiania
- mov bx,offset bools_czy_pierwszy
- cmp byte ptr ds:[bx],1 ;jeśli pierwszy to znaczy, że nic nie przerobiiśmy -> koniec
- je fclose
- mov byte ptr [bx],1
- for_in_files: ;przepisujemy kolejne linie z plików wejściowych
- xor ax,ax
- mov bx,offset ile_wejsciowych
- mov al,byte ptr ds:[bx] ;sprawdzenie czy przerobiliśmy tą linię we wszystkich plikach?
- cmp di,ax
- je write_a_new_line
- mov bx,offset bools_zrobione
- cmp byte ptr [bx+di],0 ;sprawdzenie czy skończyliśmy pracę z tym plikiem?
- je continue
- jne write_a_separator
- inc di ;Jesli plik został przerobiony pomijam go i zaczynam dla kolejnego
- jmp for_in_files
- continue: ;przepisywanie pojedynczej linii dla pliku
- mov si,di
- shl si,1 ;si mnożymy razy dwa bo word
- mov bx,offset bools_czy_pierwszy
- cmp byte ptr ds:[bx],1 ; czy wstawic separator
- jne write_a_separator
- mov byte ptr ds:[bx],0 ;nie wpisuje separatora na początku, a potem już tak
- jmp inner_loop
- write_a_separator: ;nie jest to pierwszy znak więc wpisuje
- mov bx,offset bools_wyjsciowy
- cmp byte ptr ds:[bx],1 ;sprawdzam piszemy do pliku czy na konsole
- je file_separator
- call print_separator
- jmp inner_loop
- file_separator:
- call file_put_separator
- inner_loop:
- call fread
- cmp cx,ax ;Czy to koniec pliku?
- jne eof
- cmp byte ptr ds:[znak],13 ;Czy to znak nowej linii?
- je read_and_jump
- ;Albo wpisujemy nasz znak do pliku albo na konsole
- mov dx,offset znak ;Na potrzeby procedur printf oraz fprintf
- mov bx,offset bools_wyjsciowy
- cmp byte ptr ds:[bx],1 ;do pliku czy na konsole?
- jne console_write
- call fprintf ;Do pliku
- jmp inner_loop
- console_write: ;Na konsole
- call printf
- jmp inner_loop
- read_and_jump: ;Nowa linia więc zczytuje bit == 10
- call fread
- inc di ;Zmieniam pliczek
- jmp for_in_files
- eof: ;Jesli napotkałem koniec pliku
- mov bx,offset bools_zrobione
- mov byte ptr ds:[bx+di],1 ;Zaznaczam że dany plik jest już przerobiony
- inc di
- jmp for_in_files
- write_a_new_line:
- mov bx,offset bools_czy_pierwszy ;Nie drukuje ostatniej nowej linii
- cmp byte ptr ds:[bx],1
- je cmd_is_parsed
- mov bx,offset bools_wyjsciowy
- cmp byte ptr ds:[bx],1 ;Czy na konsole czy do pliku
- jne console_new_line
- call file_new_line ;Do pliku
- jmp cmd_is_parsed
- console_new_line: ;Na konsole
- call print_new_line
- jmp cmd_is_parsed
- ; PROCEDURY
- ;procedura wyswietlania pomocy - poprawnej skladni
- wyswietl_pomoc:
- cmp byte ptr es:[di+1],20h
- ja throw_zla_skladnia
- mov dx,offset pomoc
- call printf
- jmp exit
- ;procedura rzucająca blad
- throw_exception:
- mov dx,offset blad
- call printf
- jmp exit
- ;procedura konczaca program, gdy pojawi sie blad skladniowy
- throw_zla_skladnia:
- mov dx,offset zla_skladnia
- call printf
- mov dx,offset pomoc
- call printf
- jmp exit
- ;procedura kończy program kiedy wybrano opcję -o a mimo tego nie podano nazwy pliku wyjściowego
- throw_brak_o:
- mov dx,offset brak_o
- call printf
- jmp exit
- ;procudura kończy program gdy wywołano opcję -o więcej niż jeden raz
- throw_za_duzo_o:
- mov dx,offset za_duzo_o
- call printf
- jmp exit
- ;procedura otwierająca plik wejsciowy/wyjsciowy
- ;tryb otwierania znajduje się w al,a w si to co należy dodać do offsetu z bx
- fopen:
- mov ah,3dh ;Otwieram plik do odczytu
- int 21h ;Otwieram plik
- jc throw_problem_plik_wejsciowy
- ;Udało nam się otworzyć plik więc należy zapisać uchwyt
- mov ds:[bx+si],ax ;Wpisujemy uchwyt otrzymany w ax,do ds:[bx+si]
- ret
- ;procedura kończy program jeśli istnieje problem z odczytaniem/zapisaniem pliku
- throw_problem_plik_wejsciowy:
- mov dx,offset problem_plik_wejsciowy
- call printf
- jmp exit
- ;procedura pobiera z pliku wejściowego o uchwycie ds:[pliki_wejsciowe_uchwyty + si] jeden znak
- fread:
- mov bx,offset pliki_wejsciowe_uchwyty
- mov ax,ds:[bx+si]
- mov bx,ax ;W bx mam uchwyt do odpowiedniego pliku wejściowego
- xor ax,ax
- mov ah,3fh ;Mówię procesorowi że czytam z pliku
- mov cx,1 ;1 bajt danych == 1 znak
- mov dx,offset znak ;Zczytuje go do zmiennej znak
- int 21h ;W ax siedzi ilość pobranych znaków
- jc throw_exception
- ret
- ;procedura wpisuje do pliku którego uchwyt jest w bx,jeden bajt z adresu ds:[znak]
- fprintf:
- mov bx,ds:[plik_wyjsciowy_uchwyt] ;W bx przetrzymuje uchwyt do pliku
- xor ax,ax
- mov ah,40h
- int 21h
- jc throw_exception
- ret
- ;procedura wpisuje do pliku separator
- file_put_separator:
- mov dx,offset separator
- call fprintf
- ret
- ;procedura wpisuje nową linię do pliku (rozmiar linii to 2 bajty)
- file_new_line:
- mov cx,2
- mov dx,offset nwln
- call fprintf
- ret
- ;procedura zamyka plik wyjściowy, a następnie kończy program
- fclose:
- mov bx,ds:[plik_wyjsciowy_uchwyt] ;W bx przechowuje uchwyt zamykanego pliku
- xor ax,ax
- mov ah,3eh
- int 21h
- jmp exit
- ;procedura wypluwa separator na konsole
- print_separator:
- mov dx,offset separator
- call printf
- ret
- ;procedura wypluwa na konsole nowa linię
- print_new_line:
- mov dx,offset nwln
- call printf
- ret
- ;procedura wypisuje na ekran zawartość ds:dx
- printf:
- mov ah,9
- int 21h
- ret
- ;procedura, ktora konczy program
- exit:
- mov ah,04ch
- int 21h
- main endp
- code ends
- end start
Add Comment
Please, Sign In to add comment