;=============================================================================;
; ;
; Plik : arch2.asm ;
; Format : COM ;
; Cwiczenie : Kod U2 ;
; Autorzy : Bartosz Kapusta,Wojciech Kaszyński ,6 ,wtorek ,11:00 ;
; Data zaliczenia: 05.04.2011 ;
; Uwagi : Program wczytuje z klawiatury dwie liczby calkowite ;
; z przedzialu [-32768..32767] wprowadzane w postaci znakow ;
; ASCII, konwertuje je do 16-bitowej postaci obliczeniowej ;
; w kodzie U2, oblicza ich sume reprezentowana w 32-bitowej ;
; postaci kodu U2, a nastepnie dokonuje jej konwersji do ;
; postaci znakow ASCII i wyswietla ja w tej postaci na ;
; ekranie. ;
;=============================================================================;
.MODEL TINY
MAX_ZNAKOW EQU 6 ; maksymalna liczba znakow
; liczby wprowadzanej przez
; uzytkownika
CRLF EQU 13,10 ; znak nowej linii
ENTERR EQU 13 ; klawisz enter
KOD SEGMENT
ORG 100h ; przesuniecie o 256 bajtow
ASSUME CS:Kod ; jedyny segment programu wskazujacy na to ze program jest typu .com
WczytajZnak MACRO
; Dzialanie:
; Makro wczytuje znak z klawiatury bez echa.
; Uzywane rejestry:
; AH
mov ah, 08h
int 21h
ENDM
WyswietlZnak MACRO Znak
; Dzialanie:
; Makro wyswietla podany znak na ekranie.
; Parametry:
; Znak - znak do wyswietlenia
; Uzywane rejestry:
; AH, DL
mov dl, Znak
mov ah, 02h
int 21h
ENDM
WyswietlNapis MACRO Napis
; Dzialanie:
; Makro wyswietla podany napis zakonczony znakiem '$' na ekranie.
; Parametry:
; Napis - napis do wyswietlenia
; Uzywane rejestry:
; AH, DX
mov dx, OFFSET Napis
mov ah, 09h
int 21h
ENDM
WczytISkonwU2 MACRO Bufor, LiczbaZnakow
local doit
; Dzialanie:
; Makro wczytuje z klawiatury znaki traktujac je jako liczbe
; w postaci ciagu znakow ASCII i konwertuje ja do postaci obliczeniowej
; w kodzie U2.
; Parametry:
; Bufor - bufor, gdzie umieszczane beda wczytywane znaki
; LiczbaZnakow - maksymalna liczba znakow do wczytania
; Wyjscie:
; CF - 0 gdy powodzenie, 1 gdy niepowodzenie
; AX - o ile CF=0 - skonwertowana liczba w kodzie U2
; Uzywane rejestry:
; BX, CX
doit:
mov bx, OFFSET Bufor ;wczytujemy poczatek bufora
mov cx, LiczbaZnakow
call WczytajLiczbe ;wykonujemy skok do wcztania liczby
mov bx, OFFSET Bufor
mov cx, LiczbaZnakow ;wczytujemy do rejestru cx ilosc znakow wpisanych przez uzytkownika
call Zakres ;sprawdzamy zakres
jc doit ;skok jesli cf=1
mov bx, OFFSET Bufor ;wczytujemy poczatek bufora ponownie ,liczba jest ok
mov cx, LiczbaZnakow ;wczytujemy do rejestru cx ilosc znakow wpisanych przez uzytkownika
call KonwertujLiczbe ;wykonujemy skok do konwertowania liczby
ENDM
Sumuj MACRO Skladnik1, Skladnik2, Suma
mov ax, Skladnik1 ; pobierz pierwszy skladnik
add ax, Skladnik2 ; dodaj drugi skladnik
mov WORD PTR Suma, ax ; zapamietaj mlodsze slowo
jmp druga ; wyniku w zmiennej
pierwsza:
jo ZFOF ; skok jesli wystapil nadmiar ZF=OF=1
jmp ZF ; skok jesli ZF=1, OF=0
druga:
jz pierwsza ; skok jezeli zf=1
jo ZF ; skok jesli wystapil nadmiar ZF=0,OF=1
js ZFOF ; skok jesli liczba jest ujemna ,ZF=OF=0, SF=1
jmp ZF ; a jak nie to dodatnia
ZFOF:
mov WORD PTR Suma + 2, 0FFFFh
jmp koniec_proc
ZF:
mov WORD PTR Suma + 2, 0 ; zapelnij zerem starsze bajty
koniec_proc:
ENDM
SkonwASCII MACRO Liczba, Bufor
LOCAL Cyfra
; Dzialanie:
; Makro konwertuje liczbe z 32-bitowej postaci obliczeniowej do postaci
; ciagu znakow ASCII, ktore zapamietuje w buforze.
; Parametry:
; Liczba - konwertowana liczba w 32-bitowej postaci obliczeniowej
; Bufor - bufor, gdzie umieszczone beda znaki liczby po konwersji
; Uzywane rejestry:
; AX, BL, DI
push dx ; odkladamy rejestry wykorzystywane na stos
mov ax, WORD PTR Liczba ; pobierz liczbe
mov di, OFFSET Bufor ; ustaw wskaznik na poczatek
; bufora
mov cx,0
mov dx, WORD PTR Liczba + 2
cmp dx, 0FFFFh ; porownujemy dx z 65535
jne plus ; jezeli nie to oznacza ze liczba jest dodatnia poniewaz nie ma na poczatku '1'
mov dl, 45 ;wkladamy do dl 45
mov [di], dl
inc di
cmp ax, 0
jne negacja
mov dx, 54
push dx ; zdejmujemy rejestry wykorzystywane w procedurze ze stosu
inc cx ; zwiekszamy wskaznik
jmp plus
negacja:
neg ax ;negujemy rejestr ax
plus:
mov dx, 0 ; zerujemy rejestr dx
cmp ax, 10 ; czy liczba mniejsza niz 10?
jb Cyfra ; tak - skocz
mov bx, 10 ; wkladamy dzielnik do bx
div bx ; dzielimy przez 10
add dx, 48 ; skonwertuj starsza cyfre do postaci ASCII
inc cx ; zwiekszamy wskaznik
push dx ; odkladamy rejestr wykorzystywany na stos
jmp plus
Cyfra:
add al, '0' ; skonwertuj cyfre do postaci ASCII
mov [di], al ; zapamietaj otrzymany znak w buforze
inc di ; zwieksz pozycje wskaznika
znaczek:
cmp cx, 0
je koniec
pop dx ; zdjemujemy rejestr ze stosu
mov [di], dx ; zapamietaj otrzymany znak w buforze
inc di ; zwiekszamy wskaźnik
loop znaczek
koniec:
mov BYTE PTR [di], '$' ; oznacz koniec stringa
pop dx ; zdjemujemy rejestr ze stosu
ENDM
poczatek:
jmp start ; skok do programu glownego
Skladnik1 DW (?) ; pierwsza liczba
Skladnik2 DW (?) ; druga liczba
ileznakow DW (?) ; ilosc znakow wpisanych przez uzytkownika
Suma DD (?) ; suma dwoch skladnikow
Bufor1 DW MAX_ZNAKOW DUP (?) ; bufor dla pierwszego skladnika
Bufor2 DW MAX_ZNAKOW DUP (?) ; bufor dla drugiego skladnika
BuforWynik DB MAX_ZNAKOW + 2 DUP (?) ; bufora dla sumy dwoch skladnikow
txtPowitanie DB "Program sumuje dwie liczby calkowite z zakresu " ; tekst wyswietlany przy uruchomieniu programu
DB "[-32768..32767].$"
txtZlec1 DB CRLF,"Podaj pierwsza liczbe: $" ;prosba o podanie pierwszej liczby
txtZlec2 DB CRLF,"Podaj druga liczbe: $" ;prosba o podanie drugiej liczby
txtZakresZly DB CRLF,"Podana przez Ciebie liczba znajduje sie poza zakresem! Podaj liczbe z przedzialu [-32768,32767] : $" ; wyswietlenie informacji o zlej liczbie wpisanej przez uzytkownika
txtWynik DB CRLF,"Wynik wynosi: $" ; wyswietlenie informacji o wyniku dodawania
minimum DB "32768" ; minimalna liczba ktora moze wpisac uzytkownik
maximum DB "32767" ; maxymalna liczba ktora moze wpisac uzytkownik
Zakres PROC NEAR
; Dzialanie:
; Procedura sprawdza czy liczba podana przez uzytkownika znajduje sie w
; zakresie [-32768;32767]
; Uzywane rejestry:
; AX, CX, BX
push ax ;odkladamy rejestr wykorzystywany w procedurze na stos
mov cx, ileznakow ;wkladamy do rejestru ilosc znakow wpisanych przez uzytkownika
cmp cx, 5 ; czy liczba ma 5 znakow ?
jbe good ; jesli jest mniej lub 5 znakow to robimy skok do etykiety good
mov al, [bx] ;czy ma 5 znakow ? jak tak to sprawdzamy dalej
cmp al, '-' ;czy liczba ma '-'?
je Sprawdzujemna ;jezeli jest'-' robimy skok do etykiety sprawdzujemna
mov si, OFFSET maximum ;wkladamy do wskaznika wartosc maxymalna
jmp spr
Sprawdzujemna:
mov si, OFFSET minimum ;wkladamy do wskaznika wartosc minimalna
dec cx ; zmniejszamy wskaznik
inc bx ; opuszczamy '-' wpisany przez uzytkownika
cmp cx, 5 ; czy po opuszczeniu ma 5 znakow ?
jb good ; jesli liczba ma mniej niz 5 znakow wykonujemy skok do etykiety good
spr:
mov al, [bx] ; wkladamy cyfre aktualnie znajdujaca sie w bx do rejestru al
cmp al, [si] ; porownujemy liczbe z zakresem wartosci
jb good ; jesli zakres jest ok , robimy skok do good
cmp al, [si] ; porownujemy liczbe z zakresem wartosci
ja bad ; jezeli zakres jest zly , robimy skok do bad
inc bx ; zwiekszamy wskaznik
inc si ; zwiekszamy wskaznik
loop spr
good:
clc ; cf = 0
jmp koniecsprawdzania ; zakres jest ok, konczymy sprawdzanie
bad:
WyswietlNapis txtZakresZly ; wyswietlamy informacje o wpisaniu przez uzytkownika liczby spoza zakresu
stc ; cf = 1
koniecsprawdzania:
pop ax ; zdejmujemy rejestr wykorzystywany w procedurze ze stosu
ret ; poprawne zakonczenie procedury
Zakres ENDP
WczytajLiczbe PROC NEAR
; Dzialanie:
; Procedura wczytuje ciag znakow z klawiatury stanowiacych liczbe
; w postaci ASCII i zapisuje je do bufora. Przeprowadzana jest kontrola
; dopuszczalnosci wprowadzanych znakow.
; Wejscie:
; DS:BX - bufor
; CX - maksymalna liczba znakow do wczytania
; Wyjscie:
; Brak
push ax ; odloz rejestry wykorzystywane w procedurze
push dx
kolejnyznak:
WczytajZnak ; wczytaj znak bez echa
cmp al, '-' ; czy znak jest minus?
je ujemna ; tak - przejdz do zapamietania
cmp al, '0' ; czy znak jest cyfra?
jb kolejnyznak ; nie - ignoruj znak i przejdz do wczytania
; kolejnego
cmp al, '9'
ja kolejnyznak ; jesli znak jest wiekszy od 9 , ponownie wczytujemy znak
dec cx ; zmniejszamy wskaznik
ujemna:
mov [bx], al ; tak - zapamietaj znak w buforze
inc bx ; zwieksz pozycje wskaznika w buforze
WyswietlZnak al ; wyswietl wczytany znak
dec cx ; zmniejszamy wskaznik
Wczytywanie:
WczytajZnak ; wczytaj znak bez echa
cmp cx, 4 ;jesli nie ma jeszcze zadnej cyfry nie sprawdzaj entera
ja bezcrlf
cmp al, ENTERR ; czy zostal wcisniety enter?
jne bezcrlf ; jezeli nie ma to sprawdzamy dalej
jmp loaded ; zostal wcisniety enter, konczymy wczytywanie
bezcrlf:
cmp al, '0' ; czy znak jest cyfra?
jb Wczytywanie ; nie - ignoruj znak i przejdz do wczytania
; kolejnego
cmp al, '9'
ja Wczytywanie ; jesli wieksze od 9 , wczytujemy ponownie
mov [bx], al ; tak - zapamietaj znak w buforze
inc bx ; zwieksz pozycje wskaznika w buforze
WyswietlZnak al ; wyswietl wczytany znak
loop Wczytywanie ; przejdz do wczytania kolejnego znaku, o ile
loaded: ; nie wczytano juz wszystkich
mov dx, MAX_ZNAKOW ; wkladamy do dx maxymalna ilosc znakow jaka moze wpisac uzytkownik
sub dx, cx ; odejmujemy wartosc wskaznika w ktorym aktualnie sie znajduje od maxymalnej ilosci
mov ileznakow, dx ; otrzymujemy ilosc znakow wpisanych przez uzytkownika
cmp cx, 0 ;czy liczba 5-cyfrowa?
jne endit ; jesli nie jest to konczymy
Enterek:
WczytajZnak ; jesli liczba jest 5-cyfrowa, to poczekaj
cmp al, ENTERR ; na zatwierdzenie enterem
jne Enterek ; jesli nie zostal wcisniety enter to czekamy na niego
endit:
pop dx ; odtworz rejestry wykorzystywane w procedurze
pop ax
ret
WczytajLiczbe ENDP
KonwertujLiczbe PROC NEAR
; Dzialanie:
; Procedura konwertuje liczbe zapisana w buforze w postaci ciagu znakow
; ASCII do 16-bitowej postaci obliczeniowej w kodzie U2.
; Wejscie:
; DS:BX - bufor
; Wyjscie:
; CF - 0 gdy powodzenie, 1 gdy niepowodzenie
; AX - o ile CF=0 - skonwertowana liczba w kodzie U2
;; DO ZROBIENIA:
;; Zmodyfikowac procedure umozliwoajac konwersje liczb z pelnego zakresu.
;; W przypadku stwierdzenia sytuacji uniemozliwiajacej poprawne konwersje
;; zwrocic informacje o niepowodzeniu ustawiajac znacznik CF.
push dx ; odkladamy rejestry wykorzystywane w procedurze
mov cx, ileznakow ; wkladamy do wskaznika ilosc znakow wpisanych przez uzytkownika
mov si, bx
mov al, [bx]
cmp al, '-' ; czy liczba wpisana przez uzytkownika jest ujemna ?
jne signit ; liczba jest dodatnia
inc bx ; pomijamy znak '-' wpisany przez uzytkownika
signit:
dec cx ;zmniejszamy wskaznik
dec cx ;zmniejszamy wskaznik
mov ax, cx
nextto:
cmp cx, 0
je next
inc bx
loop nextto
next:
mov cx, ax
mov ax, 1
mov dx, [bx]
xor dh, dh
sub dx, 48 ;zamieniam kod ascii na cyfre, odejmujac 48
cmp cx, 0
je endofconversion
dalej:
dec bx
push bx ;wstawiamy ciag na stos
push dx ;wstawiamy liczbe na stos
mov dx, 10 ;ustalam mnoznik ax * 10
mul dx ;mnoze ax
mov dx, [bx] ;do dx przekladam znak
mov dh, 0
sub dx, 48 ;zamieniam kod ascii na cyfre
push ax ; odkladam mnoznik
mul dx ;mnoze ax razy znak
pop bx ;pobieram mnoznik do bx
pop dx ;pobieram liczbe
add dx, ax ;dodaje do liczby wynik mnozenia
mov ax, bx ;przywracam do ax mnoznik
pop bx ;pobieram ciag znakow
loop dalej
endofconversion:
mov al, [si]
cmp al, '-' ; czy liczba wpisana przez uzytkownika jest ujemna ?
jne dodatnia ; dodatnia
neg dx
dodatnia:
mov ax, dx
clc ; ustaw znacznik, ze procedura zakonczyla sie
; poprawnie
pop dx
ret
KonwertujLiczbe ENDP
Start:
mov ax, seg kod
mov ds, ax
WyswietlNapis txtPowitanie ; wyswietl napis powitalny
WyswietlNapis txtZlec1 ; wyswietl napis nakazujacy
; wprowadzenie 1-szej liczby
WczytISkonwU2 Bufor1, MAX_ZNAKOW ; wczytaj liczbe z
; z klawiatury i
; skonwertuj do
; postaci U2
jc Blad ; jezeli wystapil blad - skocz
mov Skladnik1, ax ; w przeciwnym razie zapamietaj
; skonwertowana liczbe w zmiennej
WyswietlNapis txtZlec2 ; wyswietl napis nakazujacy
; wprowadzenie 2-giej liczby
wczytiskonwu2 bufor2, MAX_ZNAKOW ;konwersja2 Bufor2, MAX_ZNAKOW
; wczytaj liczbe z
; z klawiatury i
; skonwertuj do
; postaci U2
jnc Zsumuj ; jezeli nie wystapil blad - skocz
Blad:
mov ax, 4C01h ; w przeciwnym razie zakoncz program
int 21h ; z kodem powrotu oznaczajacym
; wystapienie bledu
Zsumuj:
mov Skladnik2, ax ; zapamietaj skonwertowana liczbe
; w zmiennej
Sumuj Skladnik1, Skladnik2, Suma ; zsumuj obie
; wprowadzone liczby
; i zapamietaj wynik
; w zmiennej
SkonwASCII Suma, BuforWynik ; skonwertuj wynik do postaci
; ASCII i zapamietaj w buforze
WyswietlNapis txtWynik ; wyswietl napis informujacy o wyniku
WyswietlNapis BuforWynik ; wyswietl wynik w postaci
; ASCII
mov ax, 4C00h ; zakoncz program z kodem powrotu
int 21h ; zakonczenia poprawnego
Kod ENDS ;koniec segmentu
END Poczatek ;wywolanie etykiety poczatek