Kod:
.MODEL SMALL
Kod SEGMENT
MAX_ZNAKOW EQU 7 ; maksymalna liczba znakow
; liczby wprowadzanej przez
; uzytkownika
CRLF EQU 13,10 ; znak nowej linii
ORG 100h
ASSUME CS:Kod
Start:
jmp WlasciwaEtykieta
Skladnik1 DW (?)
Skladnik2 DW (?)
Suma DD (?)
BuforWynik DB MAX_ZNAKOW + 2 DUP (?)
txtPowitanie DB "Program sumuje dwie liczby calkowite $"
txtBladZakresu DB CRLF,"Podano liczbe zbyt duza $"
txtZlec1 DB CRLF,"Podaj pierwsza liczbe: $"
txtZlec2 DB CRLF,"Podaj druga liczbe: $"
txtWynik DB CRLF,"Wynik to: $"
;---------------------MAKRA
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
;
Sumuj MACRO Skladnik1, Skladnik2,Suma
mov ax, Skladnik1 ; pobiera pierwszy skladnik
add ax, Skladnik2 ; dodaje do niego drugi skladnik
mov WORD PTR Suma, ax ; wprowadza mlodsze slowo z ax do zmiennej Suma
js ujemne ; jesli liczba jest ujemna (SF=1), to skacze do etykiety ujemne
jo wypelnjedynkami ; jesli wystapil nadmiar (OF=1), to skacze do etykiety wypelnjedynkami
jmp wypelnzerami ; gdy liczba jest dodatnia i nie wystapil nadmiar (SF=0 i OF=0), to skacze do etykiety wypelnzerami
ujemne:
jo wypelnzerami ; liczba jest ujemna, jesli wystapil nadmiar (OF=1), to skacze do etykiety wypelnzerami
; jesli nie wystapil nadmiar, to skacze do etykiety wypelnjedynkami
wypelnjedynkami:
mov dx, 0ffffh
mov WORD PTR Suma + 2, dx ; wpisuje jedynki do starszego slowa
jmp KoniecSumowania
wypelnzerami:
mov dx,0000h
mov WORD PTR Suma + 2, dx ; wpisuje zera do starszego slowa
KoniecSumowania:
ENDM
;
KonwASCII MACRO Liczba, Bufor
xor ax,ax ; zeruje ax
mov ax, WORD PTR Liczba ; pobiera mlodsze slowo liczby
mov dx, WORD PTR Liczba + 2 ; pobiera starsze slowo liczby
mov di, OFFSET Bufor ; ustawia wskaznik na poczatek bufora
cmp dx, 80h ; sprawdza bit znaku
; if below - nie ma 4 jedynek na poczštku liczby
jb Dodatnia ; jesli liczba jest dodatnia, to skacze do etykiety Dodatnia
mov bl, '-'
mov [di], bl ; wysyla znak minus do lancucha wyjsciowego
inc di ; zwieksza pozycje wskaznika
xor dx, 0ffffh ; konwertuje liczbe na jej modul
xor ax, 0ffffh ; w obu rejestrach
add ax, 1 ; -||-
adc dx, 0 ; -||- dodanie CF na wypadek przekroczenia zakresu
Dodatnia:
mov bx, 10 ; definiuje dzielnik
xor cx, cx ; zeruje CX
Podziel:
div bx ; dzielenie ax przez bx
push dx ; odklada na stos reszte z dzielenia
xor dx, dx ; zeruje dx
inc cx ; zwieksza licznik petli, pobierajacej dane ze stosu
cmp ax, 0 ; porownuje wynik dzielenia z zerem
ja Podziel ; jesli wynik dzielenia jest dodatni, powtarza dzielenie
ZapiszZnak:
pop dx ; pobiera ze stosu reszte z dzielenia
add dx, '0' ; konwertuje na kod ASCII danej cyfry
mov [di], dx ; wysyla liczbe w ASCII do lancucha wyjsciowego
inc di ; zwieksza pozycje wskaznika
loop ZapiszZnak ; wykona sie tyle razy ile wynosi CX, czyli tyle razy, ile bylo wczesniej dzielen
mov BYTE PTR [di], '$' ; umieszcza znak konca lancucha tekstowego na koncu bufora
ENDM
;
;--------------------PROCEDURY
WczytajLiczbe PROC NEAR ; konwersja dokonywana na miejscu
; Dzialanie:
; Procedura wczytuje znak z klawiatury stanowiacy liczbe
; w postaci ASCII nastepnie dokonuje jego konwersji do postaci obliczeniowej(zachowanej w AX)
; którš dodaje do ogolnego wyniku(postac liczby) przechwywanego w DX
;
push ax ; odloz rejestry wykorzystywane w procedurze
push dx
xor bx,bx ; zeruje BX gdzie przechowuje aktualna liczbe wpisana przez uzytkownika
xor cx,cx
mov cx,1 ; zakladam ze liczba jest dodatnia
Wczytaj:
WczytajZnak ; wczytaj znak bez echa
cmp al, 0Dh ; sprawdza czy to enter
je ent
cmp al, '0' ; czy znak jest cyfra?
jb Sprawdz_minus ; nie - ignoruj znak i przejdz do wczytania
; kolejnego
cmp al, '9'
ja Wczytaj
cmp al, '-'
jb kl_niechciany ; ("-")
WyswietlZnak al ; wyswietl wczytany znak
sub al,'0' ; konwersja do postaci obliczeniowej
xor ah,ah ; wynik znajduje sie w AX
push AX ; odkladam AX na stos
mov AX,BX ; wkladam bx do ax (poniewaz operacja MUL mnozy rejestr AX)
mov DX,000Ah ; przygotowywuje liczbe 10 do mnozenia
mul DX ; mnoze zawartosc AX(czyli wynik) przez 10 (przesuwam o jedno miejsce w lewo)
mov BX,AX
pop AX
add BX,AX
push BX
add BX,CX
cmp BX,8000h ; sprawdzam czy nie przekroczono zakresu
ja przekroczenie
pop BX
jmp Wczytaj ; przejdz do wczytania kolejnego znaku, o ile
; nie wczytano juz wszystkich
ent:
cmp cx,0 ; zakoncz odrazu jesli liczba jest dodatnia(CX!=0)
jne zakonczenie
neg bx ; a jesli jest ujemna(CX==0) dokonaj negacji bitow w celu konwersji na postac U2
jmp zakonczenie ; ... i zakoncz
przekroczenie:
WyswietlNapis txtBladZakresu
mov ax, 4C01h
int 21h
zakonczenie:
pop dx
pop ax
mov dx, bx ; zapisz wynik do DX
clc ; ustaw znacznik o poprawnosci procedury
ret
WczytajLiczbe ENDP
;
Sprawdz_minus PROC NEAR
; procedura sprawdzajaca czy podany znak jest minusem
; a nastepnie ustawiajaca wartosc CX na 0 jeli jest ujemna
cmp cx,0
je Wczytaj
cmp al, '-' ; sprawdza czy pierwszy znak jest minusem
jne Wczytaj
mov cx,0000h ; jesli liczba jest ujemna, to cx=0
WyswietlZnak al
jmp Wczytaj
Sprawdz_minus ENDP
;
kl_niechciany: ;wcisniety klawisz, ktory nas nie interesuje
cmp al, '-'
je wczytaj
WlasciwaEtykieta:
WyswietlNapis txtPowitanie ; wyswietl napis powitalny
WyswietlNapis txtZlec1 ; wyswietl napis nakazujacy
call WczytajLiczbe ; uruchom procedura wczytania i konwersji
mov Skladnik1,dx ; przepisz wynik z poprzedniej procedury do Skladnik1
WyswietlNapis txtZlec2
call WczytajLiczbe
mov Skladnik2,dx
jmp Zsumuj ; skok do procedury Sumujacej
mov ax, 4C01h
int 21h
Zsumuj:
Sumuj Skladnik1, Skladnik2,Suma ; zsumuj obie
; wprowadzone liczby
; i zapamietaj wynik
; w zmiennej Suma
KonwASCII 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
END Start