[Assembler] Sprawdzenie czy podana wartosc jest liczba


(Marek Gadzalski) #1

Witam,

Mam do napisania program, ktory bedzie dodawał liczby z zadanego zakresu oraz sprawdzał czy podane liczby spelniał pewne wymagania. Jednym z tych wymagań jest sprawdzenie czy wprowadzana wartosc jesli libczą(wystąpienie znaku minus(-) w liczbie). Niestety nie wiem jak przejść po całej liczbie i sprawdzić czy wystapil minus.

.MODEL  SMALL

DosIntr        equ    21h

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

wart1       DW      (?)

wart2       DW      (?)

Suma            DD      (?)

BuforWynik      DB      MAX_ZNAKOW + 2 DUP (?)

txtPowitanie    DB      "Ten program sumuje dwie liczby calkowite $"

txtBladZakresu  DB      CRLF,"Podano liczbe za duza $"

txtZlec1        DB      CRLF,"Podaj pierwsza wartosc: $"

txtZlec2        DB      CRLF,"Podaj druga wartosc: $"

tekst2        DB 'Zle wpisana liczba',10,13,'$'

txtWynik        DB      CRLF,"Wynik to: $"

WczytajZnak     MACRO

; Dzialanie:

; Makro wczytuje znak z klawiatury, uzywane rejestry to AH

     mov     ah, 08h

     int     21h

   ENDM

WyswietlZnak    MACRO   Znak

; Dzialanie:

; Makro wyswietla podany znak na ekranie, 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, uzywane rejestry: AH, DX

              mov     dx, OFFSET Napis

              mov     ah, 09h

              int     21h

          ENDM

Sumuj           MACRO   wart1, wart2,Suma

; Dzialanie:

; dodaje dwie liczby 16-bitowe, i zapamietuje wynik w postaci 32-bitowej, uzywane rejestry AX

                mov     ax, wart1           ; pobiera pierwszy skladnik

                add     ax, wart2           ; 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

WczytajLiczbe   PROC NEAR                  ; konwersja dokonywana na miejscu

; Dzialanie:

; 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     ax, '0'         ; czy znak jest cyfra?

                jb      Sprawdz_minus   ; nie - ignoruj znak i przejdz do wczytania

                                        ; kolejnego

    

                cmp     al, '9'

                ja      Wczytaj

                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

komentarz2:    mov dx,offset tekst2

        mov ah,9

        int DosIntr

        jmp zakonczenie

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

WlasciwaEtykieta:

                WyswietlNapis txtPowitanie      ; wyswietl napis powitalny

                

                WyswietlNapis txtZlec1            ; wyswietl napis nakazujacy

                call WczytajLiczbe              ; uruchom procedura wczytania i konwersji

                mov wart1,dx                   ; przepisz wynik z poprzedniej procedury do wart1

                WyswietlNapis txtZlec2      

                call WczytajLiczbe              

                mov wart2,dx        

                jmp     Zsumuj                   ; skok do procedury Sumujacej

                mov     ax, 4C01h

                int     21h

Zsumuj:

                Sumuj   wart1, wart2,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