; Program do zamiany wzoru na Odwrotna Notacje Polska ; ; Autor: Bogdan D. ; kontakt: bogdandr (malpka) op (kropka) pl ; ; kompilacja: ; ; nasm -f elf onp.asm ; ld -s -o onp onp.o ; ; Copyright (C) 2005-2007 Bogdan 'bogdro' Drozdowski, bogdandr @ op . pl ; ; Ten program jest wolnym oprogramowaniem; mozesz go rozpowszechniac ; i/lub modyfikowac zgodnie z licencja GNU Lesser General Public License ; (GNU LGPL) w wersji wydanej przez Fundacje Wolnego Oprogramowania; ; wedlug wersji 3 Licencji lub (jesli wolisz) jednej z pozniejszych wersji. ; ; Ten program jest udostepniany z nadzieja, ze bedzie uzyteczny, lecz ; BEZ JAKIEJKOLWIEK GWARANCJI; nawet domyslnej gwarancji PRZYDATNOSCI ; HANDLOWEJ albo PRZYDATNOSCI DO OKRESLONYCH ZASTOSOWAN. W celu uzyskania ; blizszych informacji - Licencja GNU Lesser General Public License. ; ; Z pewnoscia wraz z niniejszym programem otrzymales tez egzemplarz ; Licencji GNU Lesser General Public License; jesli nie - napisz do ; Fundacji Wolnego Oprogramowania: ; Free Software Foundation ; 51 Franklin Street, Fifth Floor ; Boston, MA 02110-1301 ; USA %idefine bksp 8 ; definicje kilku znakow %idefine tab 9 %idefine lf 10 %idefine cr 13 %idefine spc ' ' %idefine escp 27 section .text global _start _start: push ebp mov ebp, esp mov eax, 4 ; funkcja zapisu do pliku mov ebx, 1 ; stdout (ekran) mov ecx, info ; napis mov edx, info_dl ; ile bajtow piszemy int 80h ; wyswietlamy prosbe o nazwe pliku %idefine argc ebp+4 %idefine argv ebp+8 mov eax, [argc] ; sprawdzamy, ile podano ; nam argumentow cmp eax, 1 ja z_arg mov eax, 4 ; funkcja zapisu do pliku mov ebx, 1 ; stdout (ekran) mov ecx, podaj ; napis mov edx, podaj_dl ; ile bajtow piszemy int 80h ; wyswietlamy prosbe o nazwe pliku mov eax, 3 ; funkcja odczytu z pliku xor ebx, ebx ; EBX = 0 = stdin (klawiatura) mov ecx, wejscie ; gdzie zapisujemy odczytane dane mov edx, 100h ; ile bajtow chcemy int 80h ; wykonaj mov byte [wejscie+0ffh], 0 ; na wszelki wypadek mov byte [wejscie+eax-1], 0 ; napis konczymy zerem input_juz: mov esi, -1 ; indeks do lancucha wejsciowego xor edi, edi ; indeks do lancucha wyjsciowego xor ebx, ebx ; indeks do stosu przetwarzaj: xor eax, eax ; wyzeruj biezacy znak AL ; i priorytet AH inc esi ; przejdz do kolejnego znaku mov al, [wejscie+esi] ; pobierz znak ; pomijamy biale znaki cmp al, spc je przetwarzaj cmp al, tab je przetwarzaj test al, al jz koniec_przetw ; wychodzimy na bajcie zerowym ; ----------------------- cmp al, '0' ; jesli cyfra/zmienna, to ; przepisz do "wyj" jb niecyfra cmp al, '9' ja niecyfra mov [wyj + edi], al ; zapisz do lancucha wyjsciowego inc edi ; DI pokazuje na kolejne wolne miejsce mov byte [byla_zmienna], 1 jmp short przetwarzaj ; ----------------------- niecyfra: ; sprawdzmy, czy litera: cmp al, 'A' jb nielitera cmp al, 'Z' ja spr_male mov [wyj + edi], al inc edi mov byte [byla_zmienna], 1 jmp short przetwarzaj spr_male: cmp al, 'a' jb nielitera cmp al, 'z' ja nielitera mov [wyj + edi], al inc edi mov byte [byla_zmienna], 1 jmp short przetwarzaj ; ----------------------- nielitera: cmp byte [byla_zmienna], 1 jne bez_spacji mov byte [wyj + edi], spc inc edi mov byte [byla_zmienna], 0 bez_spacji: cmp al, '(' ; jesli nawias (, to na stos jne nie_nawias_l mov [stosik+ebx], ax ; wpisz na stos add ebx, 2 ; BX pokazuje na kolejne wolne miejsce jmp przetwarzaj ; ----------------------- nie_nawias_l: ; operator dzialania ; priorytety: {'(', 0)}, {'+','-',')', 1} ; {'*','/', 2}, { '^', 3 } cmp al, '+' jne nie_plus mov ah, 1 ; priorytet jmp short prior_juz nie_plus: cmp al, '-' jne nie_minus mov ah, 1 ; priorytet jmp short prior_juz nie_minus: cmp al, ')' jne nie_nawias_p ; jesli nawias ")", to przepisz ze ; stosu wszystko do "(" wlacznie .przepisuj: test ebx, ebx jz zly_token ; sprawdz, czy nie koniec stosu sub ebx, 2 ; przejdz na poprzednia wartosc ; na stosie mov cl, [stosik+ebx] cmp cl, '(' je short .juz ; konczymy przepisywanie, gdy ; trafimy na '(' mov [wyj+edi], cl ; przepisz do lancucha wyjsciowego inc edi jmp short .przepisuj .juz: ; mov ah, 1 ; priorytet ; jmp short prior_juz jmp przetwarzaj nie_nawias_p: cmp al, '*' jne nie_mnoz mov ah, 2 ; priorytet jmp short prior_juz nie_mnoz: cmp al, '/' jne nie_dziel mov ah, 2 ; priorytet jmp short prior_juz nie_dziel: cmp al, '^' jne zly_token mov ah, 3 ; priorytet ; jmp short prior_juz prior_juz: ; jesli stos pusty, wpisz na ; wierzch stosu test ebx, ebx jnz .testuj_inne mov [ebx+stosik], ax add ebx, 2 jmp przetwarzaj .testuj_inne: cmp [stosik+ebx-1], ah ; porownujemy prior. biezacego ; operatora z tym na stosie ; jesli priorytet oper. na stosie ; jest mniejszy, ; wpisz na wierzch stosu jae .zdejmuj mov [ebx+stosik], ax add ebx, 2 jmp przetwarzaj .zdejmuj: test ebx, ebx jz zly_token ; sprawdz, czy stos nie jest pusty sub ebx, 2 ; zdejmujemy ze stosu wszystkie ; operatory o wiekszym lub rownym ; priorytecie mov cl, [ebx+stosik] ; pobierz znak ze stosu mov [wyj+edi], cl ; zapisz do lancucha wyjsciowego inc edi cmp [stosik+ebx-1], ah ; znowu porownaj priorytet jae .zdejmuj ; i dalej zdejmuj, jesli trzeba mov [ebx+stosik], ax ; a biezacy znak dopisz na stos add ebx, 2 jmp przetwarzaj zly_token: mov [zly_znak], al mov eax, 4 ; funckja zapisu do pliku mov ebx, 1 ; ekran mov ecx, zly ; napis mov edx, zly_dl ; dlugosc napisu int 80h ; wypisz info o zlym znaku jmp short koniec ; ----------------------- koniec_przetw: test ebx, ebx jz juz ; sprawdz, czy stos nie jest pusty sub ebx, 2 ;przejdz na wczesniejszy znak ze stosu ; przepisz stos do wyjscia mov al, [stosik+ebx] mov [wyj+edi], al inc edi ; DI wskazuje na kolejne miejsce ; na kolejny znak jmp short koniec_przetw juz: cld mov al, 10 ; wyliczamy dlugosc wyniku - szukamy ; znaku konca linii mov edi, wyj mov ecx, 100h repne scasb mov edx, edi sub edx, wyj ; ECX = dlugosc wyniku mov eax, 4 ; funkcja pisania do pliku mov ebx, 1 ; ekran mov ecx, wynik ; napis add edx, wynik_dl ; dlugosc napisu int 80h ; wyswietl wynik ; ==================================== koniec: mov eax, 1 ; wyjscie z programu xor ebx, ebx int 80h ; ************************************ z_arg: ; trafimy tu, gdy podano cos nam ; na linii polecen cld mov al, 0 mov esi, [argv+4] mov edi, [argv+4] mov ecx, 100h repne scasb ; znajdz koniec argumentu ; pierwszy arg. to nazwa programu mov ecx, edi ; przepisz drugi arg. do nazwy pliku sub ecx, esi inc ecx mov edi, wejscie rep movsb mov byte [wejscie+0ffh], 0 jmp input_juz ; ==================================== section .data info db 'Program zamienia wyrazenie na Odwrotna Notacje Polska.',lf info_dl equ $ - info podaj db 'Podaj wyrazenie: ' podaj_dl equ $ - podaj zly db lf, 'Nieprawidlowy token: ' zly_znak db ' ' zly_dl equ $ - zly wynik db lf, 'Wynik: ' wynik_dl equ $ - wynik wyj times 100h db 10 ; znaki przejscia do nowej linii byla_zmienna db 0 wejscie times 100h db 0 stosik times 200h db 0